1/* 2 * Xv driver for SiS 300, 315 and 330 series. 3 * 4 * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1) Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2) Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3) The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Author: Thomas Winischhofer <thomas@winischhofer.net> 29 * 30 * Formerly based on a mostly non-working code fragment for the 630 by 31 * Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan which is 32 * Copyright (C) 2000 Silicon Integrated Systems Corp, Inc. 33 * 34 * Basic structure based on the mga Xv driver by Mark Vojkovich 35 * and i810 Xv driver by Jonathan Bian <jonathan.bian@intel.com>. 36 * 37 * All comments in this file are by Thomas Winischhofer. 38 * 39 * The overlay adaptor supports the following chipsets: 40 * SiS300: No registers >0x65, two overlays (one used for CRT1, one for CRT2) 41 * SiS630/730: No registers >0x6b, two overlays (one used for CRT1, one for CRT2) 42 * SiS550: Full register range, two overlays (one used for CRT1, one for CRT2) 43 * SiS315: Full register range, one overlay (used for both CRT1 and CRT2 alt.) 44 * SiS650/740: Full register range, one overlay (used for both CRT1 and CRT2 alt.) 45 * SiSM650/651: Full register range, two overlays (one used for CRT1, one for CRT2) 46 * SiS330: Full register range, one overlay (used for both CRT1 and CRT2 alt.) 47 * SiS661/741/760: Full register range, two overlays (one used for CRT1, one for CRT2) 48 * SiS340: - ? overlays. Extended registers for DDA. 49 * SiS761: - ? overlays. Extended registers for DDA. 50 * XGI Volari V3XT/V5/V8: 1 Overlay. Extended registers for DDA. 51 * 52 * Help for reading the code: 53 * 315/550/650/740/M650/651/330/661/741/76x/340/XGI = SIS_315_VGA 54 * 300/630/730 = SIS_300_VGA 55 * For chipsets with 2 overlays, hasTwoOverlays will be true 56 * 57 * Notes on display modes: 58 * 59 * -) dual head mode: 60 * DISPMODE is either SINGLE1 or SINGLE2, hence you need to check dualHeadMode flag 61 * DISPMODE is _never_ MIRROR. 62 * a) Chipsets with 2 overlays: 63 * 315/330 series: Only half sized overlays available (width 960), 660: 1536 64 * Overlay 1 is used on CRT1, overlay 2 for CRT2. 65 * b) Chipsets with 1 overlay: 66 * Full size overlays available. 67 * Overlay is used for either CRT1 or CRT2 68 * -) merged fb mode: 69 * a) Chipsets with 2 overlays: 70 * 315/330 series: Only half sized overlays available (width 960), 660: 1536 71 * DISPMODE is always MIRROR. Overlay 1 is used for CRT1, overlay 2 for CRT2. 72 * b) Chipsets with 1 overlay: 73 * Full size overlays available. 74 * DISPMODE is either SINGLE1 or SINGLE2. Overlay is used accordingly on either 75 * CRT1 or CRT2 (automatically, where it is located) 76 * -) mirror mode (without dualhead or mergedfb) 77 * a) Chipsets with 2 overlays: 78 * 315/330 series: Only half sized overlays available (width 960), 660: 1536 79 * DISPMODE is MIRROR. Overlay 1 is used for CRT1, overlay 2 for CRT2. 80 * b) Chipsets with 1 overlay: 81 * Full size overlays available. 82 * DISPMODE is either SINGLE1 or SINGLE2. Overlay is used depending on 83 * XvOnCRT2 flag. 84 * 85 * About the video blitter: 86 * The video blitter adaptor supports 16 ports. By default, adaptor 0 will 87 * be the overlay adaptor, adaptor 1 the video blitter. The option XvDefaultAdaptor 88 * allows reversing this. 89 * Since SiS does not provide information on the 3D engine, I could not 90 * implement scaling. Instead, the driver paints a black border around the unscaled 91 * video if the destination area is bigger than the video. 92 * 93 */ 94 95#ifdef HAVE_CONFIG_H 96#include "config.h" 97#endif 98 99#include "sis.h" 100#ifdef SIS_USE_XAA 101#include "xf86fbman.h" 102#endif 103#include "regionstr.h" 104 105#include "xf86xv.h" 106#include <X11/extensions/Xv.h> 107#include "dixstruct.h" 108#include "fourcc.h" 109 110#define SIS_NEED_inSISREG 111#define SIS_NEED_outSISREG 112#define SIS_NEED_inSISIDXREG 113#define SIS_NEED_outSISIDXREG 114#define SIS_NEED_setSISIDXREGmask 115#define SIS_NEED_MYMMIO 116#include "sis_regs.h" 117 118#ifdef INCL_YUV_BLIT_ADAPTOR 119#include "sis310_accel.h" 120#endif 121 122#include "sis_video.h" 123 124/********************************* 125 * Raw register access * 126 *********************************/ 127 128#if 0 129static CARD32 _sisread(SISPtr pSiS, CARD32 reg) 130{ 131 return *(pSiS->IOBase + reg); 132} 133 134static void _siswrite(SISPtr pSiS, CARD32 reg, CARD32 data) 135{ 136 *(pSiS->IOBase + reg) = data; 137} 138#endif 139 140static CARD8 getsrreg(SISPtr pSiS, CARD8 reg) 141{ 142 CARD8 ret; 143 inSISIDXREG(SISSR, reg, ret); 144 return ret; 145} 146 147static CARD8 getvideoreg(SISPtr pSiS, CARD8 reg) 148{ 149 CARD8 ret; 150 inSISIDXREG(SISVID, reg, ret); 151 return ret; 152} 153 154static __inline void setvideoreg(SISPtr pSiS, CARD8 reg, CARD8 data) 155{ 156 outSISIDXREG(SISVID, reg, data); 157} 158 159static __inline void setvideoregmask(SISPtr pSiS, CARD8 reg, CARD8 data, CARD8 mask) 160{ 161 setSISIDXREGmask(SISVID, reg, data, mask); 162} 163 164static void setsrregmask(SISPtr pSiS, CARD8 reg, CARD8 data, CARD8 mask) 165{ 166 setSISIDXREGmask(SISSR, reg, data, mask); 167} 168 169/* VBlank */ 170static CARD8 vblank_active_CRT1(SISPtr pSiS, SISPortPrivPtr pPriv) 171{ 172 return(inSISREG(SISINPSTAT) & 0x08); /* Verified */ 173} 174 175static CARD8 vblank_active_CRT2(SISPtr pSiS, SISPortPrivPtr pPriv) 176{ 177 CARD8 ret; 178 179 if(pPriv->bridgeIsSlave) return(vblank_active_CRT1(pSiS, pPriv)); 180 181 if(pSiS->VGAEngine == SIS_315_VGA) { 182 inSISIDXREG(SISPART1, 0x30, ret); 183 } else { 184 inSISIDXREG(SISPART1, 0x25, ret); 185 } 186 return(ret & 0x02); /* Verified */ 187} 188 189/* Scanline - unused */ 190#if 0 191static CARD16 get_scanline_CRT1(SISPtr pSiS) 192{ 193 CARD32 line; 194 195 _siswrite(pSiS, REG_PRIM_CRT_COUNTER, 0x00000001); 196 line = _sisread(pSiS, REG_PRIM_CRT_COUNTER); 197 198 return((CARD16)((line >> 16) & 0x07FF)); 199} 200#endif 201 202static CARD16 get_scanline_CRT2(SISPtr pSiS, SISPortPrivPtr pPriv) 203{ 204 CARD8 reg1, reg2; 205 206 if(pSiS->VGAEngine == SIS_315_VGA) { 207 inSISIDXREG(SISPART1, 0x32, reg1); 208 inSISIDXREG(SISPART1, 0x33, reg2); 209 } else { 210 inSISIDXREG(SISPART1, 0x27, reg1); 211 inSISIDXREG(SISPART1, 0x28, reg2); 212 } 213 214 return((CARD16)(reg1 | ((reg2 & 0x70) << 4))); 215} 216 217/* Helper: Count attributes */ 218static int 219SiSCountAttributes(XF86AttributeRec *attrs) 220{ 221 int num = 0; 222 223 while(attrs[num].name) num++; 224 225 return num; 226} 227 228/********************************* 229 * Video gamma * 230 *********************************/ 231 232static void 233SiSComputeXvGamma(SISPtr pSiS) 234{ 235 int num = 255, i; 236 double red = 1.0 / (double)((double)pSiS->XvGammaRed / 1000); 237 double green = 1.0 / (double)((double)pSiS->XvGammaGreen / 1000); 238 double blue = 1.0 / (double)((double)pSiS->XvGammaBlue / 1000); 239 240 for(i = 0; i <= num; i++) { 241 pSiS->XvGammaRampRed[i] = 242 (red == 1.0) ? i : (CARD8)(pow((double)i / (double)num, red) * (double)num + 0.5); 243 244 pSiS->XvGammaRampGreen[i] = 245 (green == 1.0) ? i : (CARD8)(pow((double)i / (double)num, green) * (double)num + 0.5); 246 247 pSiS->XvGammaRampBlue[i] = 248 (blue == 1.0) ? i : (CARD8)(pow((double)i / (double)num, blue) * (double)num + 0.5); 249 } 250} 251 252static void 253SiSSetXvGamma(SISPtr pSiS) 254{ 255 int i; 256 UChar backup = getsrreg(pSiS, 0x1f); 257 setsrregmask(pSiS, 0x1f, 0x08, 0x18); 258 for(i = 0; i <= 255; i++) { 259 SIS_MMIO_OUT32(pSiS->IOBase, 0x8570, 260 (i << 24) | 261 (pSiS->XvGammaRampBlue[i] << 16) | 262 (pSiS->XvGammaRampGreen[i] << 8) | 263 pSiS->XvGammaRampRed[i]); 264 } 265 setsrregmask(pSiS, 0x1f, backup, 0xff); 266} 267 268void 269SiSUpdateXvGamma(SISPtr pSiS, SISPortPrivPtr pPriv) 270{ 271 UChar sr7 = getsrreg(pSiS, 0x07); 272 273 if(!pSiS->XvGamma) return; 274 if(!(pSiS->MiscFlags & MISC_CRT1OVERLAYGAMMA)) return; 275 276#ifdef SISDUALHEAD 277 if((pPriv->dualHeadMode) && (!pSiS->SecondHead)) return; 278#endif 279 280 if(!(sr7 & 0x04)) return; 281 282 SiSComputeXvGamma(pSiS); 283 SiSSetXvGamma(pSiS); 284} 285 286static void 287SISResetXvGamma(ScrnInfoPtr pScrn) 288{ 289 SISPtr pSiS = SISPTR(pScrn); 290 SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn); 291 292 SiSUpdateXvGamma(pSiS, pPriv); 293} 294 295/********************************* 296 * InitVideo() * 297 *********************************/ 298 299void 300SISInitVideo(ScreenPtr pScreen) 301{ 302 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 303 SISPtr pSiS = SISPTR(pScrn); 304 XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; 305 XF86VideoAdaptorPtr newAdaptor = NULL, newBlitAdaptor = NULL; 306 int num_adaptors; 307 308 newAdaptor = SISSetupImageVideo(pScreen); 309 if(newAdaptor) { 310 SISInitOffscreenImages(pScreen); 311 } 312 313#ifdef INCL_YUV_BLIT_ADAPTOR 314 if( ( (pSiS->ChipFlags & SiSCF_Is65x) || 315 (pSiS->ChipType >= SIS_330) ) && 316 (pScrn->bitsPerPixel != 8) ) { 317 newBlitAdaptor = SISSetupBlitVideo(pScreen); 318 } 319#endif 320 321 num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); 322 323 if(newAdaptor || newBlitAdaptor) { 324 int size = num_adaptors; 325 326 if(newAdaptor) size++; 327 if(newBlitAdaptor) size++; 328 329 newAdaptors = malloc(size * sizeof(XF86VideoAdaptorPtr*)); 330 if(newAdaptors) { 331 if(num_adaptors) { 332 memcpy(newAdaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr)); 333 } 334 if(pSiS->XvDefAdaptorBlit) { 335 if(newBlitAdaptor) { 336 newAdaptors[num_adaptors] = newBlitAdaptor; 337 num_adaptors++; 338 } 339 } 340 if(newAdaptor) { 341 newAdaptors[num_adaptors] = newAdaptor; 342 num_adaptors++; 343 } 344 if(!pSiS->XvDefAdaptorBlit) { 345 if(newBlitAdaptor) { 346 newAdaptors[num_adaptors] = newBlitAdaptor; 347 num_adaptors++; 348 } 349 } 350 adaptors = newAdaptors; 351 } 352 } 353 354 if(num_adaptors) { 355 xf86XVScreenInit(pScreen, adaptors, num_adaptors); 356 } 357 358 if(newAdaptors) { 359 free(newAdaptors); 360 } 361} 362 363/********************************* 364 * SetPortsDefault() * 365 *********************************/ 366 367void 368SISSetPortDefaults(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) 369{ 370 SISPtr pSiS = SISPTR(pScrn); 371#ifdef SISDUALHEAD 372 SISEntPtr pSiSEnt = pSiS->entityPrivate;; 373#endif 374 375 pPriv->colorKey = pSiS->colorKey = 0x000101fe; 376 pPriv->brightness = pSiS->XvDefBri; 377 pPriv->contrast = pSiS->XvDefCon; 378 pPriv->hue = pSiS->XvDefHue; 379 pPriv->saturation = pSiS->XvDefSat; 380 pPriv->autopaintColorKey = TRUE; 381 pPriv->disablegfx = pSiS->XvDefDisableGfx; 382 pPriv->disablegfxlr= pSiS->XvDefDisableGfxLR; 383 pSiS->disablecolorkeycurrent = pSiS->XvDisableColorKey; 384 pPriv->usechromakey = pSiS->XvUseChromaKey; 385 pPriv->insidechromakey = pSiS->XvInsideChromaKey; 386 pPriv->yuvchromakey = pSiS->XvYUVChromaKey; 387 pPriv->chromamin = pSiS->XvChromaMin; 388 pPriv->chromamax = pSiS->XvChromaMax; 389 if(pPriv->dualHeadMode) { 390#ifdef SISDUALHEAD 391 if(!pSiS->SecondHead) { 392 pPriv->tvxpos = pSiS->tvxpos; 393 pPriv->tvypos = pSiS->tvypos; 394 pPriv->updatetvxpos = TRUE; 395 pPriv->updatetvypos = TRUE; 396 } 397#endif 398 } else { 399 pPriv->tvxpos = pSiS->tvxpos; 400 pPriv->tvypos = pSiS->tvypos; 401 pPriv->updatetvxpos = TRUE; 402 pPriv->updatetvypos = TRUE; 403 } 404#ifdef SIS_CP 405 SIS_CP_VIDEO_DEF 406#endif 407 if(pPriv->dualHeadMode) { 408#ifdef SISDUALHEAD 409 pPriv->crtnum = 410 pSiSEnt->curxvcrtnum = 411 pSiSEnt->XvOnCRT2 ? 1 : 0; 412#endif 413 } else 414 pPriv->crtnum = pSiS->XvOnCRT2 ? 1 : 0; 415 416 pSiS->XvGammaRed = pSiS->XvGammaRedDef; 417 pSiS->XvGammaGreen = pSiS->XvGammaGreenDef; 418 pSiS->XvGammaBlue = pSiS->XvGammaBlueDef; 419 SiSUpdateXvGamma(pSiS, pPriv); 420} 421 422/********************************* 423 * ResetVideo() * 424 *********************************/ 425 426static void 427SISResetVideo(ScrnInfoPtr pScrn) 428{ 429 SISPtr pSiS = SISPTR(pScrn); 430 SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn); 431 432 /* Unlock registers */ 433#ifdef UNLOCK_ALWAYS 434 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 435#endif 436 if(getvideoreg (pSiS, Index_VI_Passwd) != 0xa1) { 437 setvideoreg (pSiS, Index_VI_Passwd, 0x86); 438 if(getvideoreg (pSiS, Index_VI_Passwd) != 0xa1) 439 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 440 "Xv: Video password could not unlock registers\n"); 441 } 442 443 /* Initialize first overlay (CRT1) ------------------------------- */ 444 445 /* This bit has obviously a different meaning on 315 series (linebuffer-related) */ 446 if(pSiS->VGAEngine == SIS_300_VGA) { 447 /* Write-enable video registers */ 448 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x80, 0x81); 449 } else { 450 /* Select overlay 2, clear all linebuffer related bits */ 451 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0xb1); 452 } 453 454 /* Disable overlay */ 455 setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02); 456 457 /* Disable bob de-interlacer and some strange bit */ 458 setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x82); 459 460 /* Select RGB chroma key format (300 series only) */ 461 if(pSiS->VGAEngine == SIS_300_VGA) { 462 setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x40); 463 } 464 465 /* Reset scale control and contrast */ 466 /* (Enable DDA (interpolation)) */ 467 setvideoregmask(pSiS, Index_VI_Scale_Control, 0x60, 0x60); 468 setvideoregmask(pSiS, Index_VI_Contrast_Enh_Ctrl, 0x04, 0x1F); 469 470 setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Preset_Low, 0x00); 471 setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Preset_Middle, 0x00); 472 setvideoreg(pSiS, Index_VI_UV_Buf_Preset_Low, 0x00); 473 setvideoreg(pSiS, Index_VI_UV_Buf_Preset_Middle, 0x00); 474 setvideoreg(pSiS, Index_VI_Disp_Y_UV_Buf_Preset_High, 0x00); 475 setvideoreg(pSiS, Index_VI_Play_Threshold_Low, 0x00); 476 setvideoreg(pSiS, Index_VI_Play_Threshold_High, 0x00); 477 if(pSiS->Chipset == PCI_CHIP_SIS330) { 478 /* Disable contrast enhancement (?) */ 479 setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x00, 0x10); 480 } else if(pPriv->is661741760) { 481 setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x00, 0xE0); 482 if(pPriv->is760) { 483 setvideoregmask(pSiS, Index_VI_V_Buf_Start_Over, 0x3c, 0x3c); 484 } else { /* 661, 741 */ 485 setvideoregmask(pSiS, Index_VI_V_Buf_Start_Over, 0x2c, 0x3c); 486 } 487 } else if((pSiS->Chipset == PCI_CHIP_SIS340) || 488 (pSiS->Chipset == PCI_CHIP_XGIXG20) || 489 (pSiS->Chipset == PCI_CHIP_XGIXG40)) { 490 /* Disable contrast enhancement (?) */ 491 setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x00, 0x10); 492 /* Threshold high */ 493 setvideoregmask(pSiS, 0xb5, 0x00, 0x01); 494 setvideoregmask(pSiS, 0xb6, 0x00, 0x01); 495 /* Enable horizontal, disable vertical 4-tap DDA scaler */ 496 setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x40, 0xc0); 497 set_dda_regs(pSiS, 1.0); 498 /* Enable software-flip */ 499 setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x20, 0x20); 500 /* "Disable video processor" */ 501 setsrregmask(pSiS, 0x3f, 0x00, 0x02); 502 } else if(pPriv->is761) { 503 /* Disable contrast enhancement (?) */ 504 setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x00, 0x10); 505 /* Threshold high */ 506 setvideoregmask(pSiS, 0xb5, 0x00, 0x01); 507 setvideoregmask(pSiS, 0xb6, 0x00, 0x01); 508 /* Enable horizontal, disable vertical 4-tap DDA scaler */ 509 setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x40, 0xC0); 510 /* ? */ 511 setvideoregmask(pSiS, 0xb6, 0x02, 0x02); 512 set_dda_regs(pSiS, 1.0); 513 setvideoregmask(pSiS, Index_VI_V_Buf_Start_Over, 0x00, 0x3c); 514 } 515 516 if((pSiS->ChipFlags & SiSCF_Is65x) || (pPriv->is661741760)) { 517 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0x04); 518 } 519 520 /* Reset top window position for scanline check */ 521 setvideoreg(pSiS, Index_VI_Win_Ver_Disp_Start_Low, 0x00); 522 setvideoreg(pSiS, Index_VI_Win_Ver_Over, 0x00); 523 524 /* Initialize second overlay (CRT2) - only for 300, 630/730, 550, M650/651, 661/741/660/760 */ 525 if(pSiS->hasTwoOverlays) { 526 527 if(pSiS->VGAEngine == SIS_300_VGA) { 528 /* Write-enable video registers */ 529 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x81, 0x81); 530 } else { 531 /* Select overlay 2, clear all linebuffer related bits */ 532 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, 0xb1); 533 } 534 535 /* Disable overlay */ 536 setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02); 537 538 /* Disable bob de-interlacer and some strange bit */ 539 setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x82); 540 541 /* Select RGB chroma key format */ 542 if(pSiS->VGAEngine == SIS_300_VGA) { 543 setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x40); 544 } 545 546 /* Reset scale control and contrast */ 547 /* (Enable DDA (interpolation)) */ 548 setvideoregmask(pSiS, Index_VI_Scale_Control, 0x60, 0x60); 549 setvideoregmask(pSiS, Index_VI_Contrast_Enh_Ctrl, 0x04, 0x1F); 550 551 setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Preset_Low, 0x00); 552 setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Preset_Middle, 0x00); 553 setvideoreg(pSiS, Index_VI_UV_Buf_Preset_Low, 0x00); 554 setvideoreg(pSiS, Index_VI_UV_Buf_Preset_Middle, 0x00); 555 setvideoreg(pSiS, Index_VI_Disp_Y_UV_Buf_Preset_High, 0x00); 556 setvideoreg(pSiS, Index_VI_Play_Threshold_Low, 0x00); 557 setvideoreg(pSiS, Index_VI_Play_Threshold_High, 0x00); 558 559 if(pPriv->is661741760) { 560 CARD8 temp; 561 setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x00, 0xE0); 562 switch(pSiS->ChipType) { 563 case SIS_661: temp = 0x24; break; 564 case SIS_741: temp = 0x2c; break; 565 default: temp = 0x3c; 566 } 567 setvideoregmask(pSiS, Index_VI_V_Buf_Start_Over, temp, 0x3c); 568 } else if(pPriv->is761) { 569 setvideoregmask(pSiS, Index_VI_V_Buf_Start_Over, 0x00, 0x3c); 570 } else if(pSiS->Chipset == PCI_CHIP_SIS340) { /* 2 overlays? */ 571 setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x00, 0x10); 572 setvideoregmask(pSiS, 0xb5, 0x00, 0x01); 573 setvideoregmask(pSiS, 0xb6, 0x00, 0x01); 574 setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x40, 0xC0); 575 set_dda_regs(pSiS, 1.0); 576 setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x20, 0x20); 577 } 578 579 setvideoreg(pSiS, Index_VI_Win_Ver_Disp_Start_Low, 0x00); 580 setvideoreg(pSiS, Index_VI_Win_Ver_Over, 0x00); 581 582 } 583 584 /* set default properties for overlay 1 (CRT1) -------------------------- */ 585 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0x01); 586 setvideoregmask(pSiS, Index_VI_Contrast_Enh_Ctrl, 0x04, 0x07); 587 setvideoreg(pSiS, Index_VI_Brightness, 0x20); 588 if(pSiS->VGAEngine == SIS_315_VGA) { 589 setvideoreg(pSiS, Index_VI_Hue, 0x00); 590 setvideoreg(pSiS, Index_VI_Saturation, 0x00); 591 } 592 593 /* set default properties for overlay 2(CRT2) -------------------------- */ 594 if(pSiS->hasTwoOverlays) { 595 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, 0x01); 596 setvideoregmask(pSiS, Index_VI_Contrast_Enh_Ctrl, 0x04, 0x07); 597 setvideoreg(pSiS, Index_VI_Brightness, 0x20); 598 if(pSiS->VGAEngine == SIS_315_VGA) { 599 setvideoreg(pSiS, Index_VI_Hue, 0x00); 600 setvideoreg(pSiS, Index_VI_Saturation, 0x00); 601 } 602 } 603 604 /* Reset Xv gamma correction */ 605 if(pSiS->VGAEngine == SIS_315_VGA) { 606 SiSUpdateXvGamma(pSiS, pPriv); 607 } 608 609 pPriv->mustresettap = TRUE; 610#ifdef SISMERGED 611 pPriv->mustresettap2 = TRUE; 612#endif 613} 614 615/********************************* 616 * Set displaymode * 617 *********************************/ 618 619/* Set display mode (single CRT1/CRT2, mirror). 620 * MIRROR mode is only available on chipsets with two overlays. 621 * On the other chipsets, if only CRT1 or only CRT2 are used, 622 * the correct display CRT is chosen automatically. If both 623 * CRT1 and CRT2 are connected, the user can choose between CRT1 and 624 * CRT2 by using the option XvOnCRT2. 625 */ 626 627static void 628set_dispmode(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) 629{ 630 SISPtr pSiS = SISPTR(pScrn); 631 632 pPriv->dualHeadMode = pPriv->bridgeIsSlave = FALSE; 633 634 if(SiSBridgeIsInSlaveMode(pScrn)) { 635 pPriv->bridgeIsSlave = TRUE; 636 } 637 638 if( (pSiS->VBFlags & VB_DISPMODE_MIRROR) || 639 ((pPriv->bridgeIsSlave) && (pSiS->VBFlags & DISPTYPE_DISP2)) ) { 640 if(pPriv->hasTwoOverlays) 641 pPriv->displayMode = DISPMODE_MIRROR; /* CRT1+CRT2 (2 overlays) */ 642 else if(pPriv->crtnum) 643 pPriv->displayMode = DISPMODE_SINGLE2; /* CRT2 only */ 644 else 645 pPriv->displayMode = DISPMODE_SINGLE1; /* CRT1 only */ 646 } else { 647#ifdef SISDUALHEAD 648 if(pSiS->DualHeadMode) { 649 pPriv->dualHeadMode = TRUE; 650 if(pSiS->SecondHead) 651 pPriv->displayMode = DISPMODE_SINGLE1; /* CRT1 only */ 652 else 653 pPriv->displayMode = DISPMODE_SINGLE2; /* CRT2 only */ 654 } else 655#endif 656 if(pSiS->VBFlags & DISPTYPE_DISP1) { 657 pPriv->displayMode = DISPMODE_SINGLE1; /* CRT1 only */ 658 } else { 659 pPriv->displayMode = DISPMODE_SINGLE2; /* CRT2 only */ 660 } 661 } 662} 663 664static void 665set_disptype_regs(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) 666{ 667 SISPtr pSiS = SISPTR(pScrn); 668#ifdef SISDUALHEAD 669 SISEntPtr pSiSEnt = pSiS->entityPrivate; 670 int crtnum = 0; 671 672 if(pPriv->dualHeadMode) crtnum = pSiSEnt->curxvcrtnum; 673#endif 674 675 /* 676 * SR06[7:6] 677 * Bit 7: Enable overlay 1 on CRT2 678 * Bit 6: Enable overlay 0 on CRT2 679 * SR32[7:6] 680 * Bit 7: DCLK/TCLK overlay 1 681 * 0=DCLK (overlay on CRT1) 682 * 1=TCLK (overlay on CRT2) 683 * Bit 6: DCLK/TCLK overlay 0 684 * 0=DCLK (overlay on CRT1) 685 * 1=TCLK (overlay on CRT2) 686 * 687 * On chipsets with two overlays, we can freely select and also 688 * have a mirror mode. However, we use overlay 0 for CRT1 and 689 * overlay 1 for CRT2. 690 * ATTENTION: CRT2 can only take up to 1 (one) overlay. Setting 691 * SR06/32 to 0xc0 DOES NOT WORK. THAT'S CONFIRMED. 692 * Therefore, we use overlay 0 on CRT2 if in SINGLE2 mode. 693 * 694 * For chipsets with only one overlay, user must choose whether 695 * to display the overlay on CRT1 or CRT2 by setting XvOnCRT2 696 * to TRUE (CRT2) or FALSE (CRT1). The driver does this auto- 697 * matically if only CRT1 or only CRT2 is used. 698 */ 699#ifdef UNLOCK_ALWAYS 700 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 701#endif 702 703 switch (pPriv->displayMode) 704 { 705 case DISPMODE_SINGLE1: /* CRT1-only mode: */ 706 if(pPriv->hasTwoOverlays) { 707 if(pPriv->dualHeadMode) { 708 setsrregmask(pSiS, 0x06, 0x00, 0x40); /* overlay 0 -> CRT1 */ 709 setsrregmask(pSiS, 0x32, 0x00, 0x40); 710 } else { 711 setsrregmask(pSiS, 0x06, 0x00, 0xc0); /* both overlays -> CRT1 */ 712 setsrregmask(pSiS, 0x32, 0x00, 0xc0); 713 } 714 } else { 715#ifdef SISDUALHEAD 716 if((!pPriv->dualHeadMode) || (crtnum == 0)) { 717#endif 718 setsrregmask(pSiS, 0x06, 0x00, 0xc0); /* only overlay -> CRT1 */ 719 setsrregmask(pSiS, 0x32, 0x00, 0xc0); 720#ifdef SISDUALHEAD 721 } 722#endif 723 } 724 break; 725 726 case DISPMODE_SINGLE2: /* CRT2-only mode: */ 727 if(pPriv->hasTwoOverlays) { 728 if(pPriv->dualHeadMode) { 729 setsrregmask(pSiS, 0x06, 0x80, 0x80); /* overlay 1 -> CRT2 */ 730 setsrregmask(pSiS, 0x32, 0x80, 0x80); 731 } else { 732 setsrregmask(pSiS, 0x06, 0x40, 0xc0); /* overlay 0 -> CRT2 */ 733 setsrregmask(pSiS, 0x32, 0xc0, 0xc0); /* (although both clocks for CRT2!) */ 734 } 735 } else { 736#ifdef SISDUALHEAD 737 if((!pPriv->dualHeadMode) || (crtnum == 1)) { 738#endif 739 if(pSiS->MiscFlags & MISC_SIS760ONEOVERLAY) { 740 setsrregmask(pSiS, 0x06, 0x40, 0xc0); /* overlay 0 -> CRT2 */ 741 setsrregmask(pSiS, 0x32, 0xc0, 0xc0); /* (although both clocks for CRT2!) */ 742 } else { 743 setsrregmask(pSiS, 0x06, 0x40, 0xc0); /* only overlay -> CRT2 */ 744 setsrregmask(pSiS, 0x32, 0x40, 0xc0); 745 } 746#ifdef SISDUALHEAD 747 } 748#endif 749 } 750 break; 751 752 case DISPMODE_MIRROR: /* CRT1+CRT2-mode: (only on chips with 2 overlays) */ 753 default: 754 setsrregmask(pSiS, 0x06, 0x80, 0xc0); /* overlay 0 -> CRT1, overlay 1 -> CRT2 */ 755 setsrregmask(pSiS, 0x32, 0x80, 0xc0); 756 break; 757 } 758} 759 760static void 761set_hastwooverlays(SISPtr pSiS, SISPortPrivPtr pPriv) 762{ 763 int temp, watchdog; 764 765 if(pSiS->hasTwoOverlays) { 766 if(pSiS->MiscFlags & MISC_SIS760ONEOVERLAY) { 767 if(pPriv->hasTwoOverlays) { 768 /* Disable overlay 1 on change */ 769 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, 0x01); 770 setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x01); 771 temp = getvideoreg(pSiS,Index_VI_Control_Misc0); 772 if(temp & 0x02) { 773 watchdog = WATCHDOG_DELAY; 774 while((!vblank_active_CRT2(pSiS, pPriv)) && --watchdog); 775 watchdog = WATCHDOG_DELAY; 776 while(vblank_active_CRT2(pSiS, pPriv) && --watchdog); 777 setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02); 778 } 779 } 780 pPriv->hasTwoOverlays = FALSE; 781 } else { 782 pPriv->hasTwoOverlays = TRUE; 783 } 784 } else { 785 pPriv->hasTwoOverlays = FALSE; 786 } 787} 788 789static void 790set_allowswitchcrt(SISPtr pSiS, SISPortPrivPtr pPriv) 791{ 792 if(pPriv->hasTwoOverlays) { 793 pPriv->AllowSwitchCRT = FALSE; 794 } else if((!(pSiS->VBFlags & DISPTYPE_DISP1)) || (!(pSiS->VBFlags & DISPTYPE_DISP2))) { 795 pPriv->AllowSwitchCRT = FALSE; 796 if(!(pSiS->VBFlags & DISPTYPE_DISP1)) pPriv->crtnum = 1; 797 else pPriv->crtnum = 0; 798 } else { 799 pPriv->AllowSwitchCRT = TRUE; 800 } 801} 802 803static void 804set_maxencoding(SISPtr pSiS, SISPortPrivPtr pPriv) 805{ 806 int half; 807 808 if(pSiS->VGAEngine == SIS_300_VGA) { 809 DummyEncoding.width = IMAGE_MAX_WIDTH_300; 810 DummyEncoding.height = IMAGE_MAX_HEIGHT_300; 811 } else { 812 DummyEncoding.width = IMAGE_MAX_WIDTH_315; 813 DummyEncoding.height = IMAGE_MAX_HEIGHT_315; 814 half = IMAGE_MAX_WIDTH_315 >> 1; 815 if(pPriv->is661741760) { 816 half = 768 * 2; 817 } else if(pPriv->is340) { /* 2 overlays? */ 818 DummyEncoding.width = IMAGE_MAX_WIDTH_340; 819 half = 1280; /* ? */ 820 } else if(pPriv->is761) { 821 DummyEncoding.width = IMAGE_MAX_WIDTH_761; 822 half = 1920; /* ? */ 823 } 824 if(pPriv->hasTwoOverlays) { 825#ifdef SISDUALHEAD 826 if(pSiS->DualHeadMode) { 827 DummyEncoding.width = half; 828 } else 829#endif 830#ifdef SISMERGED 831 if(pSiS->MergedFB) { 832 DummyEncoding.width = half; 833 } else 834#endif 835 if(pPriv->displayMode == DISPMODE_MIRROR) { 836 DummyEncoding.width = half; 837 } 838 } 839 } 840} 841 842/********************************* 843 * ResetXvDisplay() * 844 *********************************/ 845 846static void 847SISResetXvDisplay(ScrnInfoPtr pScrn) 848{ 849 SISPtr pSiS = SISPTR(pScrn); 850 SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn); 851 852 if(!pPriv) return; 853 854 set_hastwooverlays(pSiS, pPriv); 855 set_allowswitchcrt(pSiS, pPriv); 856 set_dispmode(pScrn, pPriv); 857 set_maxencoding(pSiS, pPriv); 858} 859 860/********************************* 861 * SetupImageVideo() * 862 *********************************/ 863 864static XF86VideoAdaptorPtr 865SISSetupImageVideo(ScreenPtr pScreen) 866{ 867 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 868 SISPtr pSiS = SISPTR(pScrn); 869 XF86VideoAdaptorPtr adapt; 870 SISPortPrivPtr pPriv; 871 872#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,1,99,1,0) 873 XAAInfoRecPtr pXAA = pSiS->AccelInfoPtr; 874 875 if(!pXAA || !pXAA->FillSolidRects) { 876 return NULL; 877 } 878#endif 879 880 if(!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + 881 sizeof(SISPortPrivRec) + 882 sizeof(DevUnion)))) { 883 return NULL; 884 } 885 886 adapt->type = XvWindowMask | XvInputMask | XvImageMask; 887 adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; 888 adapt->name = "SIS 300/315/330 series Video Overlay"; 889 adapt->nEncodings = 1; 890 adapt->pEncodings = &DummyEncoding; 891 892 adapt->nFormats = NUM_FORMATS; 893 adapt->pFormats = SISFormats; 894 adapt->nPorts = 1; 895 adapt->pPortPrivates = (DevUnion*)(&adapt[1]); 896 897 pPriv = (SISPortPrivPtr)(&adapt->pPortPrivates[1]); 898 899 pPriv->videoStatus = 0; 900 pPriv->currentBuf = 0; 901 pPriv->handle = NULL; 902 pPriv->grabbedByV4L= FALSE; 903 pPriv->NoOverlay = FALSE; 904 pPriv->PrevOverlay = FALSE; 905 pPriv->is661741760 = ((pSiS->ChipType >= SIS_661) && 906 (pSiS->ChipType <= SIS_760)) ? TRUE : FALSE; 907 pPriv->is760 = (pSiS->ChipType == SIS_760) ? TRUE : FALSE; 908 pPriv->is761 = (pSiS->ChipType == SIS_761) ? TRUE : FALSE; 909 pPriv->is340 = (pSiS->Chipset == PCI_CHIP_SIS340) ? TRUE : FALSE; 910 pPriv->isXGI = (pSiS->Chipset == PCI_CHIP_XGIXG20 || 911 pSiS->Chipset == PCI_CHIP_XGIXG40) ? TRUE : FALSE; 912 913 /* Setup chipset type helpers */ 914 set_hastwooverlays(pSiS, pPriv); 915 set_allowswitchcrt(pSiS, pPriv); 916 917 pPriv->havetapscaler = FALSE; 918 if(pPriv->is340 || pPriv->is761 || pPriv->isXGI) { 919 pPriv->havetapscaler = TRUE; 920 } 921 922 adapt->pPortPrivates[0].ptr = (pointer)(pPriv); 923 if(pSiS->VGAEngine == SIS_300_VGA) { 924 adapt->nImages = NUM_IMAGES_300; 925 adapt->pAttributes = SISAttributes_300; 926 adapt->nAttributes = SiSCountAttributes(&SISAttributes_300[0]); 927 } else { 928 if(pSiS->ChipType >= SIS_330) { 929 adapt->nImages = NUM_IMAGES_330; 930 } else { 931 adapt->nImages = NUM_IMAGES_315; 932 } 933 adapt->pAttributes = SISAttributes_315; 934 adapt->nAttributes = SiSCountAttributes(&SISAttributes_315[0]); 935 if((pSiS->hasTwoOverlays) && (!(pSiS->SiS_SD2_Flags & SiS_SD2_SUPPORT760OO))) { 936 adapt->nAttributes--; 937 } 938 } 939 940 adapt->pImages = SISImages; 941 adapt->PutVideo = NULL; 942 adapt->PutStill = NULL; 943 adapt->GetVideo = NULL; 944 adapt->GetStill = NULL; 945 adapt->StopVideo = SISStopVideo; 946 adapt->SetPortAttribute = SISSetPortAttribute; 947 adapt->GetPortAttribute = SISGetPortAttribute; 948 adapt->QueryBestSize = SISQueryBestSize; 949 adapt->PutImage = SISPutImage; 950 adapt->QueryImageAttributes = SISQueryImageAttributes; 951 952 /* gotta uninit this someplace */ 953#if defined(REGION_NULL) 954 REGION_NULL(pScreen, &pPriv->clip); 955#else 956 REGION_INIT(pScreen, &pPriv->clip, NullBox, 0); 957#endif 958 959 pSiS->adaptor = adapt; 960 961 pSiS->xvBrightness = MAKE_ATOM(sisxvbrightness); 962 pSiS->xvContrast = MAKE_ATOM(sisxvcontrast); 963 pSiS->xvColorKey = MAKE_ATOM(sisxvcolorkey); 964 pSiS->xvSaturation = MAKE_ATOM(sisxvsaturation); 965 pSiS->xvHue = MAKE_ATOM(sisxvhue); 966 pSiS->xvSwitchCRT = MAKE_ATOM(sisxvswitchcrt); 967 pSiS->xvAutopaintColorKey = MAKE_ATOM(sisxvautopaintcolorkey); 968 pSiS->xvSetDefaults = MAKE_ATOM(sisxvsetdefaults); 969 pSiS->xvDisableGfx = MAKE_ATOM(sisxvdisablegfx); 970 pSiS->xvDisableGfxLR = MAKE_ATOM(sisxvdisablegfxlr); 971 pSiS->xvTVXPosition = MAKE_ATOM(sisxvtvxposition); 972 pSiS->xvTVYPosition = MAKE_ATOM(sisxvtvyposition); 973 pSiS->xvGammaRed = MAKE_ATOM(sisxvgammared); 974 pSiS->xvGammaGreen = MAKE_ATOM(sisxvgammagreen); 975 pSiS->xvGammaBlue = MAKE_ATOM(sisxvgammablue); 976 pSiS->xvDisableColorkey = MAKE_ATOM(sisxvdisablecolorkey); 977 pSiS->xvUseChromakey = MAKE_ATOM(sisxvusechromakey); 978 pSiS->xvInsideChromakey = MAKE_ATOM(sisxvinsidechromakey); 979 pSiS->xvYUVChromakey = MAKE_ATOM(sisxvyuvchromakey); 980 pSiS->xvChromaMin = MAKE_ATOM(sisxvchromamin); 981 pSiS->xvChromaMax = MAKE_ATOM(sisxvchromamax); 982#ifdef SISDEINT 983 pSiS->xvdeintmeth = MAKE_ATOM(sisxvdeinterlace); 984#endif 985#ifdef XV_SD_DEPRECATED 986 pSiS->xv_QVF = MAKE_ATOM(sisxvqueryvbflags); 987 pSiS->xv_GDV = MAKE_ATOM(sisxvsdgetdriverversion); 988 pSiS->xv_GHI = MAKE_ATOM(sisxvsdgethardwareinfo); 989 pSiS->xv_GBI = MAKE_ATOM(sisxvsdgetbusid); 990 pSiS->xv_QVV = MAKE_ATOM(sisxvsdqueryvbflagsversion); 991 pSiS->xv_GSF = MAKE_ATOM(sisxvsdgetsdflags); 992 pSiS->xv_GSF2 = MAKE_ATOM(sisxvsdgetsdflags2); 993 pSiS->xv_USD = MAKE_ATOM(sisxvsdunlocksisdirect); 994 pSiS->xv_SVF = MAKE_ATOM(sisxvsdsetvbflags); 995 pSiS->xv_QDD = MAKE_ATOM(sisxvsdquerydetecteddevices); 996 pSiS->xv_CT1 = MAKE_ATOM(sisxvsdcrt1status); 997 pSiS->xv_CMD = MAKE_ATOM(sisxvsdcheckmodeindexforcrt2); 998 pSiS->xv_CMDR = MAKE_ATOM(sisxvsdresultcheckmodeindexforcrt2); 999 pSiS->xv_RDT = MAKE_ATOM(sisxvsdredetectcrt2); 1000 pSiS->xv_TAF = MAKE_ATOM(sisxvsdsisantiflicker); 1001 pSiS->xv_TSA = MAKE_ATOM(sisxvsdsissaturation); 1002 pSiS->xv_TEE = MAKE_ATOM(sisxvsdsisedgeenhance); 1003 pSiS->xv_COC = MAKE_ATOM(sisxvsdsiscolcalibc); 1004 pSiS->xv_COF = MAKE_ATOM(sisxvsdsiscolcalibf); 1005 pSiS->xv_CFI = MAKE_ATOM(sisxvsdsiscfilter); 1006 pSiS->xv_YFI = MAKE_ATOM(sisxvsdsisyfilter); 1007 pSiS->xv_TCO = MAKE_ATOM(sisxvsdchcontrast); 1008 pSiS->xv_TTE = MAKE_ATOM(sisxvsdchtextenhance); 1009 pSiS->xv_TCF = MAKE_ATOM(sisxvsdchchromaflickerfilter); 1010 pSiS->xv_TLF = MAKE_ATOM(sisxvsdchlumaflickerfilter); 1011 pSiS->xv_TCC = MAKE_ATOM(sisxvsdchcvbscolor); 1012 pSiS->xv_OVR = MAKE_ATOM(sisxvsdchoverscan); 1013 pSiS->xv_SGA = MAKE_ATOM(sisxvsdenablegamma); 1014 pSiS->xv_TXS = MAKE_ATOM(sisxvsdtvxscale); 1015 pSiS->xv_TYS = MAKE_ATOM(sisxvsdtvyscale); 1016 pSiS->xv_GSS = MAKE_ATOM(sisxvsdgetscreensize); 1017 pSiS->xv_BRR = MAKE_ATOM(sisxvsdstorebrir); 1018 pSiS->xv_BRG = MAKE_ATOM(sisxvsdstorebrig); 1019 pSiS->xv_BRB = MAKE_ATOM(sisxvsdstorebrib); 1020 pSiS->xv_PBR = MAKE_ATOM(sisxvsdstorepbrir); 1021 pSiS->xv_PBG = MAKE_ATOM(sisxvsdstorepbrig); 1022 pSiS->xv_PBB = MAKE_ATOM(sisxvsdstorepbrib); 1023 pSiS->xv_BRR2 = MAKE_ATOM(sisxvsdstorebrir2); 1024 pSiS->xv_BRG2 = MAKE_ATOM(sisxvsdstorebrig2); 1025 pSiS->xv_BRB2 = MAKE_ATOM(sisxvsdstorebrib2); 1026 pSiS->xv_PBR2 = MAKE_ATOM(sisxvsdstorepbrir2); 1027 pSiS->xv_PBG2 = MAKE_ATOM(sisxvsdstorepbrig2); 1028 pSiS->xv_PBB2 = MAKE_ATOM(sisxvsdstorepbrib2); 1029 pSiS->xv_GARC2 = MAKE_ATOM(sisxvsdstoregarc2); 1030 pSiS->xv_GAGC2 = MAKE_ATOM(sisxvsdstoregagc2); 1031 pSiS->xv_GABC2 = MAKE_ATOM(sisxvsdstoregabc2); 1032 pSiS->xv_BRRC2 = MAKE_ATOM(sisxvsdstorebrirc2); 1033 pSiS->xv_BRGC2 = MAKE_ATOM(sisxvsdstorebrigc2); 1034 pSiS->xv_BRBC2 = MAKE_ATOM(sisxvsdstorebribc2); 1035 pSiS->xv_PBRC2 = MAKE_ATOM(sisxvsdstorepbrirc2); 1036 pSiS->xv_PBGC2 = MAKE_ATOM(sisxvsdstorepbrigc2); 1037 pSiS->xv_PBBC2 = MAKE_ATOM(sisxvsdstorepbribc2); 1038 pSiS->xv_SHC = MAKE_ATOM(sisxvsdhidehwcursor); 1039 pSiS->xv_PMD = MAKE_ATOM(sisxvsdpanelmode); 1040#ifdef TWDEBUG 1041 pSiS->xv_STR = MAKE_ATOM(sisxvsetreg); 1042#endif 1043#endif /* XV_SD_DEPRECATED */ 1044#ifdef SIS_CP 1045 SIS_CP_VIDEO_ATOMS 1046#endif 1047 1048 pSiS->xv_sisdirectunlocked = 0; 1049#ifdef XV_SD_DEPRECATED 1050 pSiS->xv_sd_result = 0; 1051#endif 1052 1053 /* 300 series require double words for addresses and pitches, 1054 * 315/330 series require word. 1055 */ 1056 switch (pSiS->VGAEngine) { 1057 case SIS_315_VGA: 1058 pPriv->shiftValue = 1; 1059 break; 1060 case SIS_300_VGA: 1061 default: 1062 pPriv->shiftValue = 2; 1063 break; 1064 } 1065 1066 /* Set displayMode according to VBFlags */ 1067 set_dispmode(pScrn, pPriv); 1068 1069 /* Now for the linebuffer stuff. 1070 * All chipsets have a certain number of linebuffers, each of a certain 1071 * size. The number of buffers is per overlay. 1072 * Chip number size max video size 1073 * 300 2 ? 720x576 1074 * 630/730 2 ? 720x576 1075 * 315 2 960? 1920x1080 1076 * 550 2? 960? 1920x1080? 1077 * 650/740 2 960 ("120x128") 1920x1080 1078 * M650/651.. 4 480 1920x1080 1079 * 330 2 960 1920x1080 1080 * 661/741/760 4 768 1920x1080 1081 * 340 4 1280? 1920x1080? 1082 * 761 4 1536? 1920x1080? 1083 * The unit of size is unknown; I just know that a size of 480 limits 1084 * the video source width to 384. Beyond that, line buffers must be 1085 * merged (otherwise the video output is garbled). 1086 * To use the maximum width (eg 1920x1080 on the 315 series, including 1087 * the M650, 651 and later), *all* line buffers must be merged. Hence, 1088 * we can only use one overlay. This should be set up for modes where 1089 * either only CRT1 or only CRT2 is used. 1090 * If both overlays are going to be used (such as in modes were both 1091 * CRT1 and CRT2 are active), we are limited to the half of the 1092 * maximum width, or 1536 on 661/741/760. 1093 * There is a known hardware problem with the 760 and 761 if the video 1094 * data is in the UMA area: The memory access latency is too big to 1095 * allow two overlays under some circumstances. Therefore, we must 1096 * support switching between hasTwoOverlays and !hasTwoOverlays on 1097 * the fly. 1098 */ 1099 1100 if(pSiS->VGAEngine == SIS_300_VGA) { 1101 pPriv->linebufmask = 0x11; 1102 pPriv->linebufMergeLimit = 384; 1103 } else { 1104 pPriv->linebufmask = 0xb1; 1105 pPriv->linebufMergeLimit = 384; /* should be 480 */ 1106 if(pPriv->is661741760) { 1107 pPriv->linebufMergeLimit = 576; /* should be 768 */ 1108 } else if(pPriv->is340) { 1109 pPriv->linebufMergeLimit = 1280; /* should be 1280 */ 1110 } else if(pPriv->is761) { 1111 pPriv->linebufMergeLimit = 1280; /* should be 1536 */ 1112 } else if(pPriv->isXGI) { 1113 pPriv->linebufMergeLimit = 1280; /* FIXME */ 1114 } else if(!(pPriv->hasTwoOverlays)) { 1115 pPriv->linebufMergeLimit = 720; /* should be 960 */ 1116 } 1117 /* No special treatment for 760/761 required */ 1118 } 1119 1120 set_maxencoding(pSiS, pPriv); 1121 1122 /* Reset the properties to their defaults */ 1123 SISSetPortDefaults(pScrn, pPriv); 1124 1125 /* Set SR(06, 32) registers according to DISPMODE */ 1126 set_disptype_regs(pScrn, pPriv); 1127 1128 SISResetVideo(pScrn); 1129 pSiS->ResetXv = SISResetVideo; 1130 pSiS->ResetXvDisplay = SISResetXvDisplay; 1131 if(pSiS->VGAEngine == SIS_315_VGA) { 1132 pSiS->ResetXvGamma = SISResetXvGamma; 1133 } 1134 1135 return adapt; 1136} 1137 1138#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,3,99,3,0) 1139static Bool 1140RegionsEqual(RegionPtr A, RegionPtr B) 1141{ 1142 int *dataA, *dataB; 1143 int num; 1144 1145 num = REGION_NUM_RECTS(A); 1146 if(num != REGION_NUM_RECTS(B)) 1147 return FALSE; 1148 1149 if((A->extents.x1 != B->extents.x1) || 1150 (A->extents.x2 != B->extents.x2) || 1151 (A->extents.y1 != B->extents.y1) || 1152 (A->extents.y2 != B->extents.y2)) 1153 return FALSE; 1154 1155 dataA = (int*)REGION_RECTS(A); 1156 dataB = (int*)REGION_RECTS(B); 1157 1158 while(num--) { 1159 if((dataA[0] != dataB[0]) || (dataA[1] != dataB[1])) 1160 return FALSE; 1161 dataA += 2; 1162 dataB += 2; 1163 } 1164 1165 return TRUE; 1166} 1167#endif 1168 1169/********************************* 1170 * SetPortAttribute() * 1171 *********************************/ 1172 1173void 1174SISUpdateVideoParms(SISPtr pSiS, SISPortPrivPtr pPriv) 1175{ 1176 set_hastwooverlays(pSiS, pPriv); 1177 set_allowswitchcrt(pSiS, pPriv); 1178 set_dispmode(pSiS->pScrn, pPriv); 1179 set_maxencoding(pSiS, pPriv); 1180} 1181 1182static int 1183SISSetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, 1184 INT32 value, pointer data) 1185{ 1186 SISPortPrivPtr pPriv = (SISPortPrivPtr)data; 1187 SISPtr pSiS = SISPTR(pScrn); 1188#ifdef SISDUALHEAD 1189 SISEntPtr pSiSEnt = pSiS->entityPrivate;; 1190#endif 1191 1192 if(attribute == pSiS->xvBrightness) { 1193 if((value < -128) || (value > 127)) 1194 return BadValue; 1195 pPriv->brightness = value; 1196 } else if(attribute == pSiS->xvContrast) { 1197 if((value < 0) || (value > 7)) 1198 return BadValue; 1199 pPriv->contrast = value; 1200 } else if(attribute == pSiS->xvColorKey) { 1201 pPriv->colorKey = pSiS->colorKey = value; 1202 REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 1203 } else if(attribute == pSiS->xvAutopaintColorKey) { 1204 if((value < 0) || (value > 1)) 1205 return BadValue; 1206 pPriv->autopaintColorKey = value; 1207 } else if(attribute == pSiS->xvSetDefaults) { 1208 SISSetPortDefaults(pScrn, pPriv); 1209 } else if(attribute == pSiS->xvDisableGfx) { 1210 if((value < 0) || (value > 1)) 1211 return BadValue; 1212 pPriv->disablegfx = value; 1213 } else if(attribute == pSiS->xvDisableGfxLR) { 1214 if((value < 0) || (value > 1)) 1215 return BadValue; 1216 pPriv->disablegfxlr = value; 1217 } else if(attribute == pSiS->xvTVXPosition) { 1218 if((value < -32) || (value > 32)) 1219 return BadValue; 1220 pPriv->tvxpos = value; 1221 if(pSiS->xv_sisdirectunlocked) { 1222 SiS_SetTVxposoffset(pScrn, pPriv->tvxpos); 1223 pPriv->updatetvxpos = FALSE; 1224 } else { 1225 pSiS->tvxpos = pPriv->tvxpos; 1226#ifdef SISDUALHEAD 1227 if(pPriv->dualHeadMode) pSiSEnt->tvxpos = pPriv->tvxpos; 1228#endif 1229 pPriv->updatetvxpos = TRUE; 1230 } 1231 } else if(attribute == pSiS->xvTVYPosition) { 1232 if((value < -32) || (value > 32)) return BadValue; 1233 pPriv->tvypos = value; 1234 if(pSiS->xv_sisdirectunlocked) { 1235 SiS_SetTVyposoffset(pScrn, pPriv->tvypos); 1236 pPriv->updatetvypos = FALSE; 1237 } else { 1238 pSiS->tvypos = pPriv->tvypos; 1239#ifdef SISDUALHEAD 1240 if(pPriv->dualHeadMode) pSiSEnt->tvypos = pPriv->tvypos; 1241#endif 1242 pPriv->updatetvypos = TRUE; 1243 } 1244 } else if(attribute == pSiS->xvDisableColorkey) { 1245 if((value < 0) || (value > 1)) return BadValue; 1246 pSiS->disablecolorkeycurrent = value; 1247 } else if(attribute == pSiS->xvUseChromakey) { 1248 if((value < 0) || (value > 1)) return BadValue; 1249 pPriv->usechromakey = value; 1250 } else if(attribute == pSiS->xvInsideChromakey) { 1251 if((value < 0) || (value > 1)) return BadValue; 1252 pPriv->insidechromakey = value; 1253 } else if(attribute == pSiS->xvYUVChromakey) { 1254 if((value < 0) || (value > 1)) return BadValue; 1255 pPriv->yuvchromakey = value; 1256 } else if(attribute == pSiS->xvChromaMin) { 1257 pPriv->chromamin = value; 1258 } else if(attribute == pSiS->xvChromaMax) { 1259 pPriv->chromamax = value; 1260#ifdef SISDEINT 1261 } else if(attribute == pSiS->xvdeintmeth) { 1262 if(value < 0) value = 0; 1263 if(value > 4) value = 4; 1264 pPriv->deinterlacemethod = value; 1265#endif 1266#ifdef SIS_CP 1267 SIS_CP_VIDEO_SETATTRIBUTE 1268#endif 1269 } else if(attribute == pSiS->xvHue) { 1270 if(pSiS->VGAEngine == SIS_315_VGA) { 1271 if((value < -8) || (value > 7)) return BadValue; 1272 pPriv->hue = value; 1273 } else return BadMatch; 1274 } else if(attribute == pSiS->xvSaturation) { 1275 if(pSiS->VGAEngine == SIS_315_VGA) { 1276 if((value < -7) || (value > 7)) return BadValue; 1277 pPriv->saturation = value; 1278 } else return BadMatch; 1279 } else if(attribute == pSiS->xvGammaRed) { 1280 if(pSiS->VGAEngine == SIS_315_VGA) { 1281 if((value < 100) || (value > 10000)) return BadValue; 1282 pSiS->XvGammaRed = value; 1283 SiSUpdateXvGamma(pSiS, pPriv); 1284 } else return BadMatch; 1285 } else if(attribute == pSiS->xvGammaGreen) { 1286 if(pSiS->VGAEngine == SIS_315_VGA) { 1287 if((value < 100) || (value > 10000)) return BadValue; 1288 pSiS->XvGammaGreen = value; 1289 SiSUpdateXvGamma(pSiS, pPriv); 1290 } else return BadMatch; 1291 } else if(attribute == pSiS->xvGammaBlue) { 1292 if(pSiS->VGAEngine == SIS_315_VGA) { 1293 if((value < 100) || (value > 10000)) return BadValue; 1294 pSiS->XvGammaBlue = value; 1295 SiSUpdateXvGamma(pSiS, pPriv); 1296 } else return BadMatch; 1297 } else if(attribute == pSiS->xvSwitchCRT) { 1298 if(pSiS->VGAEngine == SIS_315_VGA) { 1299 if(pPriv->AllowSwitchCRT) { 1300 if((value < 0) || (value > 1)) 1301 return BadValue; 1302 pPriv->crtnum = value; 1303#ifdef SISDUALHEAD 1304 if(pPriv->dualHeadMode) pSiSEnt->curxvcrtnum = value; 1305#endif 1306 } 1307 } else return BadMatch; 1308 } else { 1309#ifdef XV_SD_DEPRECATED 1310 return(SISSetPortUtilAttribute(pScrn, attribute, value, pPriv)); 1311#else 1312 return BadMatch; 1313#endif 1314 } 1315 return Success; 1316} 1317 1318/********************************* 1319 * GetPortAttribute() * 1320 *********************************/ 1321 1322static int 1323SISGetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, 1324 INT32 *value, pointer data) 1325{ 1326 SISPortPrivPtr pPriv = (SISPortPrivPtr)data; 1327 SISPtr pSiS = SISPTR(pScrn); 1328#ifdef SISDUALHEAD 1329 SISEntPtr pSiSEnt = pSiS->entityPrivate;; 1330#endif 1331 1332 if(attribute == pSiS->xvBrightness) { 1333 *value = pPriv->brightness; 1334 } else if(attribute == pSiS->xvContrast) { 1335 *value = pPriv->contrast; 1336 } else if(attribute == pSiS->xvColorKey) { 1337 *value = pPriv->colorKey; 1338 } else if(attribute == pSiS->xvAutopaintColorKey) { 1339 *value = (pPriv->autopaintColorKey) ? 1 : 0; 1340 } else if(attribute == pSiS->xvDisableGfx) { 1341 *value = (pPriv->disablegfx) ? 1 : 0; 1342 } else if(attribute == pSiS->xvDisableGfxLR) { 1343 *value = (pPriv->disablegfxlr) ? 1 : 0; 1344 } else if(attribute == pSiS->xvTVXPosition) { 1345 *value = SiS_GetTVxposoffset(pScrn); 1346 } else if(attribute == pSiS->xvTVYPosition) { 1347 *value = SiS_GetTVyposoffset(pScrn); 1348 } else if(attribute == pSiS->xvDisableColorkey) { 1349 *value = (pSiS->disablecolorkeycurrent) ? 1 : 0; 1350 } else if(attribute == pSiS->xvUseChromakey) { 1351 *value = (pPriv->usechromakey) ? 1 : 0; 1352 } else if(attribute == pSiS->xvInsideChromakey) { 1353 *value = (pPriv->insidechromakey) ? 1 : 0; 1354 } else if(attribute == pSiS->xvYUVChromakey) { 1355 *value = (pPriv->yuvchromakey) ? 1 : 0; 1356 } else if(attribute == pSiS->xvChromaMin) { 1357 *value = pPriv->chromamin; 1358 } else if(attribute == pSiS->xvChromaMax) { 1359 *value = pPriv->chromamax; 1360#ifdef SISDEINT 1361 } else if(attribute == pSiS->xvdeintmeth) { 1362 *value = pPriv->deinterlacemethod; 1363#endif 1364#ifdef SIS_CP 1365 SIS_CP_VIDEO_GETATTRIBUTE 1366#endif 1367 } else if(attribute == pSiS->xvHue) { 1368 if(pSiS->VGAEngine == SIS_315_VGA) { 1369 *value = pPriv->hue; 1370 } else return BadMatch; 1371 } else if(attribute == pSiS->xvSaturation) { 1372 if(pSiS->VGAEngine == SIS_315_VGA) { 1373 *value = pPriv->saturation; 1374 } else return BadMatch; 1375 } else if(attribute == pSiS->xvGammaRed) { 1376 if(pSiS->VGAEngine == SIS_315_VGA) { 1377 *value = pSiS->XvGammaRed; 1378 } else return BadMatch; 1379 } else if(attribute == pSiS->xvGammaGreen) { 1380 if(pSiS->VGAEngine == SIS_315_VGA) { 1381 *value = pSiS->XvGammaGreen; 1382 } else return BadMatch; 1383 } else if(attribute == pSiS->xvGammaBlue) { 1384 if(pSiS->VGAEngine == SIS_315_VGA) { 1385 *value = pSiS->XvGammaBlue; 1386 } else return BadMatch; 1387 } else if(attribute == pSiS->xvSwitchCRT) { 1388 if(pSiS->VGAEngine == SIS_315_VGA) { 1389#ifdef SISDUALHEAD 1390 if(pPriv->dualHeadMode) 1391 *value = pSiSEnt->curxvcrtnum; 1392 else 1393#endif 1394 *value = pPriv->crtnum; 1395 } else return BadMatch; 1396 } else { 1397#ifdef XV_SD_DEPRECATED 1398 return(SISGetPortUtilAttribute(pScrn, attribute, value, pPriv)); 1399#else 1400 return BadMatch; 1401#endif 1402 } 1403 return Success; 1404} 1405 1406/********************************* 1407 * QueryBestSize() * 1408 *********************************/ 1409 1410static void 1411SISQueryBestSize( 1412 ScrnInfoPtr pScrn, 1413 Bool motion, 1414 short vid_w, short vid_h, 1415 short drw_w, short drw_h, 1416 unsigned int *p_w, unsigned int *p_h, 1417 pointer data 1418){ 1419 *p_w = drw_w; 1420 *p_h = drw_h; 1421} 1422 1423/********************************* 1424 * Calc scaling factor * 1425 *********************************/ 1426 1427static void 1428calc_scale_factor(SISOverlayPtr pOverlay, ScrnInfoPtr pScrn, 1429 SISPortPrivPtr pPriv, int index, int iscrt2) 1430{ 1431 SISPtr pSiS = SISPTR(pScrn); 1432 CARD32 I=0,mult=0; 1433 int flag=0, flag2=0; 1434 1435 int dstW = pOverlay->dstBox.x2 - pOverlay->dstBox.x1; 1436 int dstH = pOverlay->dstBox.y2 - pOverlay->dstBox.y1; 1437 int srcW = pOverlay->srcW; 1438 int srcH = pOverlay->srcH; 1439 CARD16 LCDheight = pSiS->LCDheight; 1440 int srcPitch = pOverlay->origPitch; 1441 int origdstH = dstH; 1442 int modeflags = pOverlay->currentmode->Flags; 1443 1444 /* Stretch image due to panel link scaling */ 1445 if(pSiS->VBFlags & (CRT2_LCD | CRT1_LCDA)) { 1446 if(pPriv->bridgeIsSlave) { 1447 if(pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH)) { 1448 if(pSiS->MiscFlags & MISC_PANELLINKSCALER) { 1449 dstH = (dstH * LCDheight) / pOverlay->SCREENheight; 1450 } 1451 } 1452 } else if((iscrt2 && (pSiS->VBFlags & CRT2_LCD)) || 1453 (!iscrt2 && (pSiS->VBFlags & CRT1_LCDA))) { 1454 if((pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH)) || (pSiS->VBFlags & CRT1_LCDA)) { 1455 if(pSiS->MiscFlags & MISC_PANELLINKSCALER) { 1456 dstH = (dstH * LCDheight) / pOverlay->SCREENheight; 1457 if(pPriv->displayMode == DISPMODE_MIRROR) flag = 1; 1458 } 1459 } 1460 } 1461 if((pPriv->bridgeIsSlave || iscrt2) && 1462 (pSiS->MiscFlags & MISC_STNMODE)) { 1463 flag2 = 1; 1464 } 1465 } 1466 1467 /* For double scan modes, we need to double the height 1468 * On 315 and 550 (?), we need to double the width as well. 1469 * Interlace mode vice versa. 1470 */ 1471 if((modeflags & V_DBLSCAN) && !flag2) { 1472 dstH = origdstH << 1; 1473 flag = 0; 1474 if((pSiS->ChipType >= SIS_315H) && 1475 (pSiS->ChipType <= SIS_550)) { 1476 dstW <<= 1; 1477 } 1478 } else if(modeflags & V_INTERLACE) { 1479 dstH = origdstH >> 1; 1480 flag = 0; 1481 } 1482 1483 pOverlay->tap_scale = 1.0; 1484 1485 if(dstW < OVERLAY_MIN_WIDTH) dstW = OVERLAY_MIN_WIDTH; 1486 1487 if(dstW == srcW) { 1488 1489 pOverlay->HUSF = 0x00; 1490 pOverlay->IntBit = 0x05; 1491 pOverlay->wHPre = 0; 1492 1493 } else if(dstW > srcW) { 1494 1495 pOverlay->IntBit = 0x04; 1496 pOverlay->wHPre = 0; 1497 1498 if(pPriv->havetapscaler) { 1499 if((dstW > 2) && (srcW > 2)) { 1500 pOverlay->HUSF = (((srcW - 2) << 16) + dstW - 3) / (dstW - 2); 1501 } else { 1502 pOverlay->HUSF = ((srcW << 16) + dstW - 1) / dstW; 1503 } 1504 } else { 1505 dstW += 2; 1506 pOverlay->HUSF = (srcW << 16) / dstW; 1507 } 1508 1509 } else { 1510 1511 int tmpW = dstW; 1512 1513 /* It seems, the hardware can't scale below factor .125 (=1/8) if the 1514 pitch isn't a multiple of 256. 1515 TODO: Test this on the 315 series! 1516 */ 1517 if((srcPitch % 256) || (srcPitch < 256)) { 1518 if(((dstW * 1000) / srcW) < 125) dstW = tmpW = ((srcW * 125) / 1000) + 1; 1519 } 1520 1521 I = 0; 1522 pOverlay->IntBit = 0x01; 1523 while(srcW >= tmpW) { 1524 tmpW <<= 1; 1525 I++; 1526 } 1527 pOverlay->wHPre = (CARD8)(I - 1); 1528 dstW <<= (I - 1); 1529 1530 pOverlay->tap_scale = (float)srcW / (float)dstW; 1531 if(pOverlay->tap_scale < 1.0) pOverlay->tap_scale = 1.0; 1532 1533 if((srcW % dstW)) 1534 pOverlay->HUSF = ((srcW - dstW) << 16) / dstW; 1535 else 1536 pOverlay->HUSF = 0; 1537 } 1538 1539 if(dstH < OVERLAY_MIN_HEIGHT) dstH = OVERLAY_MIN_HEIGHT; 1540 1541 if(dstH == srcH) { 1542 1543 pOverlay->VUSF = 0x00; 1544 pOverlay->IntBit |= 0x0A; 1545 1546 } else if(dstH > srcH) { 1547 1548 dstH += 2; 1549 pOverlay->IntBit |= 0x08; 1550 1551 if(pPriv->havetapscaler) { 1552 if((dstH > 2) && (srcH > 2)) { 1553 pOverlay->VUSF = (((srcH - 2) << 16) - 32768 + dstH - 3) / (dstH - 2); 1554 } else { 1555 pOverlay->VUSF = ((srcH << 16) + dstH - 1) / dstH; 1556 } 1557 } else { 1558 pOverlay->VUSF = (srcH << 16) / dstH; 1559 } 1560 1561 } else { 1562 1563 I = srcH / dstH; 1564 pOverlay->IntBit |= 0x02; 1565 1566 if(I < 2) { 1567 pOverlay->VUSF = ((srcH - dstH) << 16) / dstH; 1568 /* Needed for LCD-scaling modes */ 1569 if((flag) && (mult = (srcH / origdstH)) >= 2) { 1570 pOverlay->pitch /= mult; 1571 } 1572 } else { 1573#if 0 1574 if(((pOverlay->bobEnable & 0x08) == 0x00) && 1575 (((srcPitch * I) >> 2) > 0xFFF)){ 1576 pOverlay->bobEnable |= 0x08; 1577 srcPitch >>= 1; 1578 } 1579#endif 1580 if(((srcPitch * I) >> 2) > 0xFFF) { 1581 I = (0xFFF * 2 / srcPitch); 1582 pOverlay->VUSF = 0xFFFF; 1583 } else { 1584 dstH = I * dstH; 1585 if(srcH % dstH) 1586 pOverlay->VUSF = ((srcH - dstH) << 16) / dstH; 1587 else 1588 pOverlay->VUSF = 0; 1589 } 1590 /* set video frame buffer offset */ 1591 pOverlay->pitch = (CARD16)(srcPitch * I); 1592 } 1593 } 1594} 1595 1596#ifdef SISMERGED 1597static void 1598calc_scale_factor_2(SISOverlayPtr pOverlay, ScrnInfoPtr pScrn, 1599 SISPortPrivPtr pPriv, int index, int iscrt2) 1600{ 1601 SISPtr pSiS = SISPTR(pScrn); 1602 CARD32 I=0,mult=0; 1603 int flag=0, flag2=0; 1604 1605 int dstW = pOverlay->dstBox2.x2 - pOverlay->dstBox2.x1; 1606 int dstH = pOverlay->dstBox2.y2 - pOverlay->dstBox2.y1; 1607 int srcW = pOverlay->srcW2; 1608 int srcH = pOverlay->srcH2; 1609 CARD16 LCDheight = pSiS->LCDheight; 1610 int srcPitch = pOverlay->origPitch; 1611 int origdstH = dstH; 1612 int modeflags = pOverlay->currentmode2->Flags; 1613 1614 /* Stretch image due to panel link scaling */ 1615 if(pSiS->VBFlags & CRT2_LCD) { 1616 if(pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH)) { 1617 if(pSiS->MiscFlags & MISC_PANELLINKSCALER) { 1618 dstH = (dstH * LCDheight) / pOverlay->SCREENheight2; 1619 flag = 1; 1620 } 1621 if(pSiS->MiscFlags & MISC_STNMODE) flag2 = 1; 1622 } 1623 } 1624 /* For double scan modes, we need to double the height 1625 * On 315 and 550 (?), we need to double the width as well. 1626 * Interlace mode vice versa. 1627 */ 1628 if((modeflags & V_DBLSCAN) && !flag2) { 1629 dstH = origdstH << 1; 1630 flag = 0; 1631 if((pSiS->ChipType >= SIS_315H) && 1632 (pSiS->ChipType <= SIS_550)) { 1633 dstW <<= 1; 1634 } 1635 } 1636 if(modeflags & V_INTERLACE) { 1637 dstH = origdstH >> 1; 1638 flag = 0; 1639 } 1640 1641 pOverlay->tap_scale2 = 1.0; 1642 1643 if(dstW < OVERLAY_MIN_WIDTH) dstW = OVERLAY_MIN_WIDTH; 1644 1645 if(dstW == srcW) { 1646 1647 pOverlay->HUSF2 = 0x00; 1648 pOverlay->IntBit2 = 0x05; 1649 pOverlay->wHPre2 = 0; 1650 1651 } else if(dstW > srcW) { 1652 1653 pOverlay->IntBit2 = 0x04; 1654 pOverlay->wHPre2 = 0; 1655 1656 if(pPriv->havetapscaler) { 1657 if((dstW > 2) && (srcW > 2)) { 1658 pOverlay->HUSF2 = (((srcW - 2) << 16) + dstW - 3) / (dstW - 2); 1659 } else { 1660 pOverlay->HUSF2 = ((srcW << 16) + dstW - 1) / dstW; 1661 } 1662 } else { 1663 dstW += 2; 1664 pOverlay->HUSF2 = (srcW << 16) / dstW; 1665 } 1666 1667 } else { 1668 1669 int tmpW = dstW; 1670 1671 /* It seems, the hardware can't scale below factor .125 (=1/8) if the 1672 pitch isn't a multiple of 256. 1673 TODO: Test this on the 315 series! 1674 */ 1675 if((srcPitch % 256) || (srcPitch < 256)) { 1676 if(((dstW * 1000) / srcW) < 125) dstW = tmpW = ((srcW * 125) / 1000) + 1; 1677 } 1678 1679 I = 0; 1680 pOverlay->IntBit2 = 0x01; 1681 while(srcW >= tmpW) { 1682 tmpW <<= 1; 1683 I++; 1684 } 1685 pOverlay->wHPre2 = (CARD8)(I - 1); 1686 dstW <<= (I - 1); 1687 1688 pOverlay->tap_scale2 = (float)srcW / (float)dstW; 1689 if(pOverlay->tap_scale2 < 1.0) pOverlay->tap_scale2 = 1.0; 1690 1691 if((srcW % dstW)) 1692 pOverlay->HUSF2 = ((srcW - dstW) << 16) / dstW; 1693 else 1694 pOverlay->HUSF2 = 0x00; 1695 } 1696 1697 if(dstH < OVERLAY_MIN_HEIGHT) dstH = OVERLAY_MIN_HEIGHT; 1698 1699 if(dstH == srcH) { 1700 1701 pOverlay->VUSF2 = 0x00; 1702 pOverlay->IntBit2 |= 0x0A; 1703 1704 } else if(dstH > srcH) { 1705 1706 dstH += 2; 1707 pOverlay->IntBit2 |= 0x08; 1708 1709 if(pPriv->havetapscaler) { 1710 if((dstH > 2) && (srcH > 2)) { 1711 pOverlay->VUSF2 = (((srcH - 2) << 16) - 32768 + dstH - 3) / (dstH - 2); 1712 } else { 1713 pOverlay->VUSF2 = ((srcH << 16) + dstH - 1) / dstH; 1714 } 1715 } else { 1716 pOverlay->VUSF2 = (srcH << 16) / dstH; 1717 } 1718 1719 } else { 1720 1721 I = srcH / dstH; 1722 pOverlay->IntBit2 |= 0x02; 1723 1724 if(I < 2) { 1725 pOverlay->VUSF2 = ((srcH - dstH) << 16) / dstH; 1726 /* Needed for LCD-scaling modes */ 1727 if(flag && ((mult = (srcH / origdstH)) >= 2)) { 1728 pOverlay->pitch2 /= mult; 1729 } 1730 } else { 1731#if 0 1732 if(((pOverlay->bobEnable & 0x08) == 0x00) && 1733 (((srcPitch * I)>>2) > 0xFFF)){ 1734 pOverlay->bobEnable |= 0x08; 1735 srcPitch >>= 1; 1736 } 1737#endif 1738 if(((srcPitch * I) >> 2) > 0xFFF) { 1739 I = (0xFFF * 2 / srcPitch); 1740 pOverlay->VUSF2 = 0xFFFF; 1741 } else { 1742 dstH = I * dstH; 1743 if(srcH % dstH) 1744 pOverlay->VUSF2 = ((srcH - dstH) << 16) / dstH; 1745 else 1746 pOverlay->VUSF2 = 0x00; 1747 } 1748 /* set video frame buffer offset */ 1749 pOverlay->pitch2 = (CARD16)(srcPitch * I); 1750 } 1751 } 1752} 1753#endif 1754 1755/********************************* 1756 * Handle 4-tap scaler (340) * 1757 *********************************/ 1758 1759static float 1760tap_dda_func(float x) 1761{ 1762 double pi = 3.14159265358979; 1763 float r = 0.5, y; 1764 1765 if(x == 0.0) { 1766 y = 1.0; 1767 } else if(x == -1.0 || x == 1.0) { 1768 y = 0.0; 1769 /* case ((x == -1.0 / (r * 2.0)) || (x == 1.0 / (r * 2.0))): */ 1770 /* y = (float)(r / 2.0 * sin(pi / (2.0 * r))); = 0.013700916287197; */ 1771 } else { 1772 y = sin(pi * x) / (pi * x) * cos(r * pi * x) / (1 - x * x); 1773 /* y = sin(pi * x) / (pi * x) * cos(r * pi * x) / (1 - 4 * r * r * x * x); */ 1774 } 1775 1776 return y; 1777} 1778 1779static void 1780set_dda_regs(SISPtr pSiS, float scale) 1781{ 1782 float W[4], WS, myadd; 1783 int *temp[4], *wm1, *wm2, *wm3, *wm4; 1784 int i, j, w, tidx, weightmatrix[16][4]; 1785 1786 for(i = 0; i < 16; i++) { 1787 1788 myadd = ((float)i) / 16.0; 1789 WS = W[0] = tap_dda_func((myadd + 1.0) / scale); 1790 W[1] = tap_dda_func(myadd / scale); 1791 WS += W[1]; 1792 W[2] = tap_dda_func((myadd - 1.0) / scale); 1793 WS += W[2]; 1794 W[3] = tap_dda_func((myadd - 2.0) / scale); 1795 WS += W[3]; 1796 1797 w = 0; 1798 for(j = 0; j < 4; j++) { 1799 weightmatrix[i][j] = (int)(((float)((W[j] * 16.0 / WS) + 0.5))); 1800 w += weightmatrix[i][j]; 1801 } 1802 1803 if(w == 12) { 1804 1805 weightmatrix[i][0]++; 1806 weightmatrix[i][1]++; 1807 weightmatrix[i][2]++; 1808 weightmatrix[i][3]++; 1809 1810 } else if(w == 20) { 1811 1812 weightmatrix[i][0]--; 1813 weightmatrix[i][1]--; 1814 weightmatrix[i][2]--; 1815 weightmatrix[i][3]--; 1816 1817 } else if(w != 16) { 1818 1819 tidx = (weightmatrix[i][0] > weightmatrix[i][1]) ? 0 : 1; 1820 temp[0] = &weightmatrix[i][tidx]; 1821 temp[1] = &weightmatrix[i][tidx ^ 1]; 1822 1823 tidx = (weightmatrix[i][2] > weightmatrix[i][3]) ? 2 : 3; 1824 temp[2] = &weightmatrix[i][tidx]; 1825 temp[3] = &weightmatrix[i][tidx ^ 1]; 1826 1827 tidx = (*(temp[0]) > *(temp[2])) ? 0 : 2; 1828 wm1 = temp[tidx]; 1829 wm2 = temp[tidx ^ 2]; 1830 1831 tidx = (*(temp[1]) > *(temp[3])) ? 1 : 3; 1832 wm3 = temp[tidx]; 1833 wm4 = temp[tidx ^ 2]; 1834 1835 switch(w) { 1836 case 13: 1837 (*wm1)++; 1838 (*wm4)++; 1839 if(*wm2 > *wm3) (*wm2)++; 1840 else (*wm3)++; 1841 break; 1842 case 14: 1843 (*wm1)++; 1844 (*wm4)++; 1845 break; 1846 case 15: 1847 (*wm1)++; 1848 break; 1849 case 17: 1850 (*wm4)--; 1851 break; 1852 case 18: 1853 (*wm1)--; 1854 (*wm4)--; 1855 break; 1856 case 19: 1857 (*wm1)--; 1858 (*wm4)--; 1859 if(*wm2 > *wm3) (*wm3)--; 1860 else (*wm2)--; 1861 } 1862 } 1863 } 1864 1865 /* Set 4-tap scaler video regs 0x75-0xb4 */ 1866 w = 0x75; 1867 for(i = 0; i < 16; i++) { 1868 for(j = 0; j < 4; j++, w++) { 1869 setvideoregmask(pSiS, w, weightmatrix[i][j], 0x3f); 1870 } 1871 } 1872} 1873 1874/********************************* 1875 * Calc line buffer size * 1876 *********************************/ 1877 1878static CARD16 1879calc_line_buf_size(CARD32 srcW, CARD8 wHPre, CARD8 planar, SISPortPrivPtr pPriv) 1880{ 1881 CARD32 I, mask = 0xffffffff, shift = pPriv->is761 ? 1 : 0; 1882 1883 if(planar) { 1884 1885 switch(wHPre & 0x07) { 1886 case 3: 1887 shift += 8; 1888 mask <<= shift; 1889 I = srcW >> shift; 1890 if((mask & srcW) != srcW) I++; 1891 I <<= 5; 1892 break; 1893 case 4: 1894 shift += 9; 1895 mask <<= shift; 1896 I = srcW >> shift; 1897 if((mask & srcW) != srcW) I++; 1898 I <<= 6; 1899 break; 1900 case 5: 1901 shift += 10; 1902 mask <<= shift; 1903 I = srcW >> shift; 1904 if((mask & srcW) != srcW) I++; 1905 I <<= 7; 1906 break; 1907 case 6: 1908 if(pPriv->is340 || pPriv->isXGI || pPriv->is761) { 1909 shift += 11; 1910 mask <<= shift; 1911 I = srcW >> shift; 1912 if((mask & srcW) != srcW) I++; 1913 I <<= 8; 1914 break; 1915 } else { 1916 return((CARD16)(255)); 1917 } 1918 default: 1919 shift += 7; 1920 mask <<= shift; 1921 I = srcW >> shift; 1922 if((mask & srcW) != srcW) I++; 1923 I <<= 4; 1924 break; 1925 } 1926 1927 } else { /* packed */ 1928 1929 shift += 3; 1930 mask <<= shift; 1931 I = srcW >> shift; 1932 if((mask & srcW) != srcW) I++; 1933 1934 } 1935 1936 if(I <= 3) I = 4; 1937 1938 return((CARD16)(I - 1)); 1939} 1940 1941static __inline void 1942calc_line_buf_size_1(SISOverlayPtr pOverlay, SISPortPrivPtr pPriv) 1943{ 1944 pOverlay->lineBufSize = 1945 calc_line_buf_size(pOverlay->srcW, pOverlay->wHPre, pOverlay->planar, pPriv); 1946} 1947 1948#ifdef SISMERGED 1949static __inline void 1950calc_line_buf_size_2(SISOverlayPtr pOverlay, SISPortPrivPtr pPriv) 1951{ 1952 pOverlay->lineBufSize2 = 1953 calc_line_buf_size(pOverlay->srcW2, pOverlay->wHPre2, pOverlay->planar, pPriv); 1954} 1955 1956/********************************** 1957 *En/Disable merging of linebuffer* 1958 **********************************/ 1959 1960static void 1961merge_line_buf_mfb(SISPtr pSiS, SISPortPrivPtr pPriv, Bool enable1, Bool enable2, 1962 short width1, short width2, short limit) 1963{ 1964 UChar misc1, misc2, mask = pPriv->linebufmask; 1965 1966 if(pPriv->hasTwoOverlays) { /* This means we are in MIRROR mode */ 1967 1968 misc2 = 0x00; 1969 if(enable1) misc1 = 0x04; 1970 else misc1 = 0x00; 1971 setvideoregmask(pSiS, Index_VI_Control_Misc2, misc2, mask); 1972 setvideoregmask(pSiS, Index_VI_Control_Misc1, misc1, 0x04); 1973 1974 misc2 = 0x01; 1975 if(enable2) misc1 = 0x04; 1976 else misc1 = 0x00; 1977 setvideoregmask(pSiS, Index_VI_Control_Misc2, misc2, mask); 1978 setvideoregmask(pSiS, Index_VI_Control_Misc1, misc1, 0x04); 1979 1980 } else { /* This means we are either in SINGLE1 or SINGLE2 mode */ 1981 1982 misc2 = 0x00; 1983 if(enable1 || enable2) { 1984 if(pSiS->MiscFlags & MISC_SIS760ONEOVERLAY) { 1985 if((width1 > (limit * 2)) || (width2 > (limit * 2))) { 1986 misc2 = 0x20; 1987 } else { 1988 misc2 = 0x10; 1989 } 1990 misc1 = 0x00; 1991 } else { 1992 misc1 = 0x04; 1993 } 1994 } else { 1995 misc1 = 0x00; 1996 } 1997 1998 setvideoregmask(pSiS, Index_VI_Control_Misc2, misc2, mask); 1999 setvideoregmask(pSiS, Index_VI_Control_Misc1, misc1, 0x04); 2000 2001 } 2002} 2003#endif 2004 2005/* About linebuffer merging: 2006 * 2007 * For example the 651: 2008 * Each overlay has 4 line buffers, 384 bytes each (<-- Is that really correct? 1920 / 384 = 5 !!!) 2009 * If the source width is greater than 384, line buffers must be merged. 2010 * Dual merge: Only O1 usable (uses overlay 2's linebuffer), maximum width 384*2 2011 * Individual merge: Both overlays available, maximum width 384*2 2012 * All merge: Only overlay 1 available, maximum width = 384*4 (<--- should be 1920, is 1536...) 2013 * 2014 * 2015 * Normally: Dual merge: Individual merge 2016 * Overlay 1 Overlay 2 Overlay 1 only! Both overlays 2017 * ___1___ ___5___ ___1___ ___2___ -\ O1 ___1___ ___2___ 2018 * ___2___ ___6___ ___3___ ___4___ \_ O 1 O1 ___3___ ___4___ 2019 * ___3___ ___7___ ___5___ ___6___ / O2 ___5___ ___6___ 2020 * ___4___ ___8___ ___7___ ___8___ -/ O2 ___7___ ___8___ 2021 * 2022 * 2023 * All merge: ___1___ ___2___ ___3___ ___4___ 2024 * (Overlay 1 only!) ___5___ ___6___ ___7___ ___8___ 2025 * 2026 * Individual merge is supported on all chipsets. 2027 * Dual merge is only supported on the 300 series and M650/651 and later. 2028 * All merge is only supported on the M650/651 and later. 2029 * Single-Overlay-chipsets only support Individual merge. 2030 * 2031 */ 2032 2033static void 2034merge_line_buf(SISPtr pSiS, SISPortPrivPtr pPriv, Bool enable, short width, short limit) 2035{ 2036 UChar misc1, misc2, mask = pPriv->linebufmask; 2037 2038 if(enable) { /* ----- enable linebuffer merge */ 2039 2040 switch(pPriv->displayMode){ 2041 case DISPMODE_SINGLE1: 2042 if(pSiS->VGAEngine == SIS_300_VGA) { 2043 if(pPriv->dualHeadMode) { 2044 misc2 = 0x00; 2045 misc1 = 0x04; 2046 } else { 2047 misc2 = 0x10; 2048 misc1 = 0x00; 2049 } 2050 } else { 2051 if(pPriv->hasTwoOverlays) { 2052 if(pPriv->dualHeadMode) { 2053 misc2 = 0x00; 2054 misc1 = 0x04; 2055 } else { 2056 if(width > (limit * 2)) { 2057 misc2 = 0x20; 2058 } else { 2059 misc2 = 0x10; 2060 } 2061 misc1 = 0x00; 2062 } 2063 } else if(pSiS->MiscFlags & MISC_SIS760ONEOVERLAY) { 2064 if(width > (limit * 2)) { 2065 misc2 = 0x20; 2066 } else { 2067 misc2 = 0x10; 2068 } 2069 misc1 = 0x00; 2070 } else { 2071 misc2 = 0x00; 2072 misc1 = 0x04; 2073 } 2074 } 2075 setvideoregmask(pSiS, Index_VI_Control_Misc2, misc2, mask); 2076 setvideoregmask(pSiS, Index_VI_Control_Misc1, misc1, 0x04); 2077 break; 2078 2079 case DISPMODE_SINGLE2: 2080 if(pSiS->VGAEngine == SIS_300_VGA) { 2081 if(pPriv->dualHeadMode) { 2082 misc2 = 0x01; 2083 misc1 = 0x04; 2084 } else { 2085 misc2 = 0x10; 2086 misc1 = 0x00; 2087 } 2088 } else { 2089 if(pPriv->hasTwoOverlays) { 2090 if(pPriv->dualHeadMode) { 2091 misc2 = 0x01; 2092 misc1 = 0x04; 2093 } else { 2094 if(width > (limit * 2)) { 2095 misc2 = 0x20; 2096 } else { 2097 misc2 = 0x10; 2098 } 2099 misc1 = 0x00; 2100 } 2101 } else if(pSiS->MiscFlags & MISC_SIS760ONEOVERLAY) { 2102 if(width > (limit * 2)) { 2103 misc2 = 0x20; 2104 } else { 2105 misc2 = 0x10; 2106 } 2107 misc1 = 0x00; 2108 } else { 2109 misc2 = 0x00; 2110 misc1 = 0x04; 2111 } 2112 } 2113 setvideoregmask(pSiS, Index_VI_Control_Misc2, misc2, mask); 2114 setvideoregmask(pSiS, Index_VI_Control_Misc1, misc1, 0x04); 2115 break; 2116 2117 case DISPMODE_MIRROR: /* This can only be on chips with 2 overlays */ 2118 default: 2119 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, mask); 2120 setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x04, 0x04); 2121 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, mask); 2122 setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x04, 0x04); 2123 break; 2124 } 2125 2126 } else { /* ----- disable linebuffer merge */ 2127 2128 switch(pPriv->displayMode) { 2129 2130 case DISPMODE_SINGLE1: 2131 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, mask); 2132 setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x04); 2133 break; 2134 2135 case DISPMODE_SINGLE2: 2136 if(pSiS->VGAEngine == SIS_300_VGA) { 2137 if(pPriv->dualHeadMode) misc2 = 0x01; 2138 else misc2 = 0x00; 2139 } else { 2140 if(pPriv->hasTwoOverlays) { 2141 if(pPriv->dualHeadMode) misc2 = 0x01; 2142 else misc2 = 0x00; 2143 } else { 2144 misc2 = 0x00; 2145 } 2146 } 2147 setvideoregmask(pSiS, Index_VI_Control_Misc2, misc2, mask); 2148 setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x04); 2149 break; 2150 2151 case DISPMODE_MIRROR: /* This can only be on chips with 2 overlays */ 2152 default: 2153 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, mask); 2154 setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x04); 2155 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, mask); 2156 setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x04); 2157 break; 2158 } 2159 } 2160} 2161 2162/********************************* 2163 * Select video format * 2164 *********************************/ 2165 2166static __inline void 2167set_format(SISPtr pSiS, SISOverlayPtr pOverlay) 2168{ 2169 CARD8 fmt; 2170 2171 switch (pOverlay->pixelFormat){ 2172 case PIXEL_FMT_YV12: 2173 case PIXEL_FMT_I420: 2174 fmt = 0x0c; 2175 break; 2176 case PIXEL_FMT_YUY2: 2177 fmt = 0x28; 2178 break; 2179 case PIXEL_FMT_UYVY: 2180 fmt = 0x08; 2181 break; 2182 case PIXEL_FMT_YVYU: 2183 fmt = 0x38; 2184 break; 2185 case PIXEL_FMT_NV12: 2186 fmt = 0x4c; 2187 break; 2188 case PIXEL_FMT_NV21: 2189 fmt = 0x5c; 2190 break; 2191 case PIXEL_FMT_RGB5: /* D[5:4] : 00 RGB555, 01 RGB 565 */ 2192 fmt = 0x00; 2193 break; 2194 case PIXEL_FMT_RGB6: 2195 fmt = 0x10; 2196 break; 2197 default: 2198 fmt = 0x00; 2199 } 2200 setvideoregmask(pSiS, Index_VI_Control_Misc0, fmt, 0xfc); 2201} 2202 2203/********************************* 2204 * Set various video registers * 2205 *********************************/ 2206 2207static __inline void 2208set_colorkey(SISPtr pSiS, CARD32 colorkey) 2209{ 2210 CARD8 r, g, b; 2211 2212 b = (CARD8)(colorkey & 0xFF); 2213 g = (CARD8)((colorkey >> 8) & 0xFF); 2214 r = (CARD8)((colorkey >> 16) & 0xFF); 2215 2216 setvideoreg(pSiS, Index_VI_Overlay_ColorKey_Blue_Min ,(CARD8)b); 2217 setvideoreg(pSiS, Index_VI_Overlay_ColorKey_Green_Min ,(CARD8)g); 2218 setvideoreg(pSiS, Index_VI_Overlay_ColorKey_Red_Min ,(CARD8)r); 2219 2220 setvideoreg(pSiS, Index_VI_Overlay_ColorKey_Blue_Max ,(CARD8)b); 2221 setvideoreg(pSiS, Index_VI_Overlay_ColorKey_Green_Max ,(CARD8)g); 2222 setvideoreg(pSiS, Index_VI_Overlay_ColorKey_Red_Max ,(CARD8)r); 2223} 2224 2225static __inline void 2226set_chromakey(SISPtr pSiS, CARD32 chromamin, CARD32 chromamax) 2227{ 2228 CARD8 r1, g1, b1; 2229 CARD8 r2, g2, b2; 2230 2231 b1 = (CARD8)(chromamin & 0xFF); 2232 g1 = (CARD8)((chromamin >> 8) & 0xFF); 2233 r1 = (CARD8)((chromamin >> 16) & 0xFF); 2234 b2 = (CARD8)(chromamax & 0xFF); 2235 g2 = (CARD8)((chromamax >> 8) & 0xFF); 2236 r2 = (CARD8)((chromamax >> 16) & 0xFF); 2237 2238 setvideoreg(pSiS, Index_VI_Overlay_ChromaKey_Blue_V_Min ,(CARD8)b1); 2239 setvideoreg(pSiS, Index_VI_Overlay_ChromaKey_Green_U_Min ,(CARD8)g1); 2240 setvideoreg(pSiS, Index_VI_Overlay_ChromaKey_Red_Y_Min ,(CARD8)r1); 2241 2242 setvideoreg(pSiS, Index_VI_Overlay_ChromaKey_Blue_V_Max ,(CARD8)b2); 2243 setvideoreg(pSiS, Index_VI_Overlay_ChromaKey_Green_U_Max ,(CARD8)g2); 2244 setvideoreg(pSiS, Index_VI_Overlay_ChromaKey_Red_Y_Max ,(CARD8)r2); 2245} 2246 2247static __inline void 2248set_brightness(SISPtr pSiS, CARD8 brightness) 2249{ 2250 setvideoreg(pSiS, Index_VI_Brightness, brightness); 2251} 2252 2253static __inline void 2254set_contrast(SISPtr pSiS, CARD8 contrast) 2255{ 2256 setvideoregmask(pSiS, Index_VI_Contrast_Enh_Ctrl, contrast, 0x07); 2257} 2258 2259/* 315 series and later only */ 2260static __inline void 2261set_saturation(SISPtr pSiS, short saturation) 2262{ 2263 CARD8 temp = 0; 2264 2265 if(saturation < 0) { 2266 temp |= 0x88; 2267 saturation = -saturation; 2268 } 2269 temp |= (saturation & 0x07); 2270 temp |= ((saturation & 0x07) << 4); 2271 2272 setvideoreg(pSiS, Index_VI_Saturation, temp); 2273} 2274 2275/* 315 series and later only */ 2276static __inline void 2277set_hue(SISPtr pSiS, CARD8 hue) 2278{ 2279 setvideoregmask(pSiS, Index_VI_Hue, (hue & 0x08) ? (hue ^ 0x07) : hue, 0x0F); 2280} 2281 2282static __inline void 2283set_disablegfx(SISPtr pSiS, Bool mybool, SISOverlayPtr pOverlay) 2284{ 2285 /* This is not supported on M65x, 65x (x>0) or later */ 2286 /* For CRT1 ONLY!!! */ 2287 if((!(pSiS->ChipFlags & SiSCF_Is65x)) && 2288 (pSiS->Chipset != PCI_CHIP_SIS660) && 2289 (pSiS->Chipset != PCI_CHIP_SIS340) && 2290 (pSiS->Chipset != PCI_CHIP_XGIXG20) && 2291 (pSiS->Chipset != PCI_CHIP_XGIXG40)) { 2292 setvideoregmask(pSiS, Index_VI_Control_Misc2, mybool ? 0x04 : 0x00, 0x04); 2293 if(mybool) pOverlay->keyOP = VI_ROP_Always; 2294 } 2295} 2296 2297static __inline void 2298set_disablegfxlr(SISPtr pSiS, Bool mybool, SISOverlayPtr pOverlay) 2299{ 2300 setvideoregmask(pSiS, Index_VI_Control_Misc1, mybool ? 0x01 : 0x00, 0x01); 2301 if(mybool) pOverlay->keyOP = VI_ROP_Always; 2302} 2303 2304#ifdef SIS_CP 2305 SIS_CP_VIDEO_SUBS 2306#endif 2307 2308/********************************* 2309 * Set main overlay registers * 2310 *********************************/ 2311 2312static void 2313set_overlay(SISPtr pSiS, SISOverlayPtr pOverlay, SISPortPrivPtr pPriv, int index, int iscrt2) 2314{ 2315 CARD8 h_over, v_over; 2316 CARD16 top, bottom, left, right, pitch = 0; 2317 CARD16 screenX, screenY; 2318 CARD32 PSY; 2319 int modeflags, totalPixels, confactor, sample, watchdog = 0; 2320 2321#ifdef SISMERGED 2322 if(pSiS->MergedFB && iscrt2) { 2323 screenX = pOverlay->currentmode2->HDisplay; 2324 screenY = pOverlay->currentmode2->VDisplay; 2325 modeflags = pOverlay->currentmode2->Flags; 2326 top = pOverlay->dstBox2.y1; 2327 bottom = pOverlay->dstBox2.y2; 2328 left = pOverlay->dstBox2.x1; 2329 right = pOverlay->dstBox2.x2; 2330 pitch = pOverlay->pitch2 >> pPriv->shiftValue; 2331 } else { 2332#endif 2333 screenX = pOverlay->currentmode->HDisplay; 2334 screenY = pOverlay->currentmode->VDisplay; 2335 modeflags = pOverlay->currentmode->Flags; 2336 top = pOverlay->dstBox.y1; 2337 bottom = pOverlay->dstBox.y2; 2338 left = pOverlay->dstBox.x1; 2339 right = pOverlay->dstBox.x2; 2340 pitch = pOverlay->pitch >> pPriv->shiftValue; 2341#ifdef SISMERGED 2342 } 2343#endif 2344 2345 if(bottom > screenY) bottom = screenY; 2346 if(right > screenX) right = screenX; 2347 2348 /* calculate contrast factor */ 2349 totalPixels = (right - left) * (bottom - top); 2350 confactor = (totalPixels - 10000) / 20000; 2351 if(confactor > 3) confactor = 3; 2352 switch(confactor) { 2353 case 1: sample = 4096 << 10; break; 2354 case 2: 2355 case 3: sample = 8192 << 10; break; 2356 default: sample = 2048 << 10; 2357 } 2358 sample /= totalPixels; 2359 confactor <<= 6; 2360 2361 /* Correct coordinates for doublescan/interlace modes */ 2362 if( (modeflags & V_DBLSCAN) && 2363 (!((pPriv->bridgeIsSlave || iscrt2) && (pSiS->MiscFlags & MISC_STNMODE))) ) { 2364 /* DoubleScan modes require Y coordinates * 2 */ 2365 top <<= 1; 2366 bottom <<= 1; 2367 } else if(modeflags & V_INTERLACE) { 2368 /* Interlace modes require Y coordinates / 2 */ 2369 top >>= 1; 2370 bottom >>= 1; 2371 } 2372 2373 h_over = (((left >> 8) & 0x0f) | ((right >> 4) & 0xf0)); 2374 v_over = (((top >> 8) & 0x0f) | ((bottom >> 4) & 0xf0)); 2375 2376 /* set line buffer size */ 2377#ifdef SISMERGED 2378 if(pSiS->MergedFB && iscrt2) { 2379 setvideoreg(pSiS, Index_VI_Line_Buffer_Size, (CARD8)pOverlay->lineBufSize2); 2380 if(pPriv->is340 || pPriv->is761 || pPriv->isXGI) { 2381 setvideoreg(pSiS, Index_VI_Line_Buffer_Size_High, (CARD8)(pOverlay->lineBufSize2 >> 8)); 2382 } 2383 } else { 2384#endif 2385 setvideoreg(pSiS, Index_VI_Line_Buffer_Size, (CARD8)pOverlay->lineBufSize); 2386 if(pPriv->is340 || pPriv->is761 || pPriv->isXGI) { 2387 setvideoreg(pSiS, Index_VI_Line_Buffer_Size_High, (CARD8)(pOverlay->lineBufSize >> 8)); 2388 } 2389#ifdef SISMERGED 2390 } 2391#endif 2392 2393 /* set color key mode */ 2394 setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, pOverlay->keyOP, 0x0f); 2395 2396 /* We don't have to wait for vertical retrace in all cases */ 2397 if(pPriv->mustwait) { 2398 if(pSiS->VGAEngine == SIS_315_VGA) { 2399 2400 if(index) { 2401 CARD16 mytop = getvideoreg(pSiS, Index_VI_Win_Ver_Disp_Start_Low); 2402 mytop |= ((getvideoreg(pSiS, Index_VI_Win_Ver_Over) & 0x0f) << 8); 2403 pOverlay->oldtop = mytop; 2404 watchdog = 0xffff; 2405 if(mytop < screenY - 2) { 2406 do { 2407 watchdog = get_scanline_CRT2(pSiS, pPriv); 2408 } while((watchdog <= mytop) || (watchdog >= screenY)); 2409 } 2410 pOverlay->oldLine = watchdog; 2411 } 2412 2413 } else { 2414 2415 watchdog = WATCHDOG_DELAY; 2416 while(pOverlay->VBlankActiveFunc(pSiS, pPriv) && --watchdog); 2417 watchdog = WATCHDOG_DELAY; 2418 while((!pOverlay->VBlankActiveFunc(pSiS, pPriv)) && --watchdog); 2419 2420 } 2421 } 2422 2423 /* Unlock address registers */ 2424 setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x20, 0x20); 2425 2426 /* Set destination window position */ 2427 setvideoreg(pSiS, Index_VI_Win_Hor_Disp_Start_Low, (CARD8)left); 2428 setvideoreg(pSiS, Index_VI_Win_Hor_Disp_End_Low, (CARD8)right); 2429 setvideoreg(pSiS, Index_VI_Win_Hor_Over, (CARD8)h_over); 2430 2431 setvideoreg(pSiS, Index_VI_Win_Ver_Disp_Start_Low, (CARD8)top); 2432 setvideoreg(pSiS, Index_VI_Win_Ver_Disp_End_Low, (CARD8)bottom); 2433 setvideoreg(pSiS, Index_VI_Win_Ver_Over, (CARD8)v_over); 2434 2435 /* Contrast factor */ 2436 setvideoregmask(pSiS, Index_VI_Contrast_Enh_Ctrl, (CARD8)confactor, 0xc0); 2437 setvideoreg(pSiS, Index_VI_Contrast_Factor, sample); 2438 2439 /* Set Y buf pitch */ 2440 setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Pitch_Low, (CARD8)(pitch)); 2441 setvideoregmask(pSiS, Index_VI_Disp_Y_UV_Buf_Pitch_Middle, (CARD8)(pitch >> 8), 0x0f); 2442 2443 /* Set Y start address */ 2444#ifdef SISMERGED 2445 if(pSiS->MergedFB && iscrt2) { 2446 PSY = pOverlay->PSY2; 2447 } else 2448#endif 2449 PSY = pOverlay->PSY; 2450 2451 setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Start_Low, (CARD8)(PSY)); 2452 setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Start_Middle, (CARD8)(PSY >> 8)); 2453 setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Start_High, (CARD8)(PSY >> 16)); 2454 2455 /* Set 315 series overflow bits for Y plane */ 2456 if(pSiS->VGAEngine == SIS_315_VGA) { 2457 setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Pitch_High, (CARD8)(pitch >> 12)); 2458 setvideoreg(pSiS, Index_VI_Y_Buf_Start_Over, ((CARD8)(PSY >> 24) & 0x03)); 2459 } 2460 2461 /* Set U/V data if using planar formats */ 2462 if(pOverlay->planar) { 2463 2464 CARD32 PSU = pOverlay->PSU; 2465 CARD32 PSV = pOverlay->PSV; 2466 2467#ifdef SISMERGED 2468 if(pSiS->MergedFB && iscrt2) { 2469 PSU = pOverlay->PSU2; 2470 PSV = pOverlay->PSV2; 2471 } 2472#endif 2473 2474 if(pOverlay->planar_shiftpitch) pitch >>= 1; 2475 2476 /* Set U/V pitch */ 2477 setvideoreg(pSiS, Index_VI_Disp_UV_Buf_Pitch_Low, (CARD8)pitch); 2478 setvideoregmask(pSiS, Index_VI_Disp_Y_UV_Buf_Pitch_Middle, (CARD8)(pitch >> 4), 0xf0); 2479 2480 /* Set U/V start address */ 2481 setvideoreg(pSiS, Index_VI_U_Buf_Start_Low, (CARD8)PSU); 2482 setvideoreg(pSiS, Index_VI_U_Buf_Start_Middle,(CARD8)(PSU >> 8)); 2483 setvideoreg(pSiS, Index_VI_U_Buf_Start_High, (CARD8)(PSU >> 16)); 2484 2485 setvideoreg(pSiS, Index_VI_V_Buf_Start_Low, (CARD8)PSV); 2486 setvideoreg(pSiS, Index_VI_V_Buf_Start_Middle,(CARD8)(PSV >> 8)); 2487 setvideoreg(pSiS, Index_VI_V_Buf_Start_High, (CARD8)(PSV >> 16)); 2488 2489 /* 315 series overflow bits */ 2490 if(pSiS->VGAEngine == SIS_315_VGA) { 2491 setvideoreg(pSiS, Index_VI_Disp_UV_Buf_Pitch_High, (CARD8)(pitch >> 12)); 2492 setvideoreg(pSiS, Index_VI_U_Buf_Start_Over, ((CARD8)(PSU >> 24) & 0x03)); 2493 if(pPriv->is661741760) { 2494 setvideoregmask(pSiS, Index_VI_V_Buf_Start_Over, ((CARD8)(PSV >> 24) & 0x03), 0xc3); 2495 } else { 2496 setvideoreg(pSiS, Index_VI_V_Buf_Start_Over, ((CARD8)(PSV >> 24) & 0x03)); 2497 } 2498 } 2499 } 2500 2501 setvideoregmask(pSiS, Index_VI_Control_Misc1, pOverlay->bobEnable, 0x1a); 2502 2503 /* Lock the address registers */ 2504 setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x20); 2505 2506 /* Set scale factor */ 2507#ifdef SISMERGED 2508 if(pSiS->MergedFB && iscrt2) { 2509 setvideoreg(pSiS, Index_VI_Hor_Post_Up_Scale_Low, (CARD8)(pOverlay->HUSF2)); 2510 setvideoreg(pSiS, Index_VI_Hor_Post_Up_Scale_High,(CARD8)((pOverlay->HUSF2) >> 8)); 2511 setvideoreg(pSiS, Index_VI_Ver_Up_Scale_Low, (CARD8)(pOverlay->VUSF2)); 2512 setvideoreg(pSiS, Index_VI_Ver_Up_Scale_High, (CARD8)((pOverlay->VUSF2) >> 8)); 2513 2514 setvideoregmask(pSiS, Index_VI_Scale_Control, (pOverlay->IntBit2 << 3) | 2515 (pOverlay->wHPre2), 0x7f); 2516 2517 if(pPriv->havetapscaler) { 2518 if((pOverlay->tap_scale2 != pOverlay->tap_scale2_old) || pPriv->mustresettap2) { 2519 set_dda_regs(pSiS, pOverlay->tap_scale2); 2520 pOverlay->tap_scale2_old = pOverlay->tap_scale2; 2521 pPriv->mustresettap2 = FALSE; 2522 } 2523 } 2524 } else { 2525#endif 2526 setvideoreg(pSiS, Index_VI_Hor_Post_Up_Scale_Low, (CARD8)(pOverlay->HUSF)); 2527 setvideoreg(pSiS, Index_VI_Hor_Post_Up_Scale_High,(CARD8)((pOverlay->HUSF) >> 8)); 2528 setvideoreg(pSiS, Index_VI_Ver_Up_Scale_Low, (CARD8)(pOverlay->VUSF)); 2529 setvideoreg(pSiS, Index_VI_Ver_Up_Scale_High, (CARD8)((pOverlay->VUSF) >> 8)); 2530 2531 setvideoregmask(pSiS, Index_VI_Scale_Control, (pOverlay->IntBit << 3) | 2532 (pOverlay->wHPre), 0x7f); 2533 if(pPriv->havetapscaler) { 2534 if((pOverlay->tap_scale != pOverlay->tap_scale_old) || pPriv->mustresettap) { 2535 set_dda_regs(pSiS, pOverlay->tap_scale); 2536 pOverlay->tap_scale_old = pOverlay->tap_scale; 2537 pPriv->mustresettap = FALSE; 2538 } 2539 } 2540#ifdef SISMERGED 2541 } 2542#endif 2543 2544} 2545 2546/********************************* 2547 * Shut down overlay * 2548 *********************************/ 2549 2550/* Overlay MUST NOT be switched off while beam is over it */ 2551static void 2552close_overlay(SISPtr pSiS, SISPortPrivPtr pPriv) 2553{ 2554 int watchdog; 2555 2556 if(!pPriv->overlayStatus) return; 2557 2558 pPriv->overlayStatus = FALSE; 2559 2560 pPriv->mustresettap = TRUE; 2561#ifdef SISMERGED 2562 pPriv->mustresettap2 = TRUE; 2563#endif 2564 2565 if(pPriv->displayMode & (DISPMODE_MIRROR | DISPMODE_SINGLE2)) { 2566 2567 /* CRT2: MIRROR or SINGLE2 2568 * 1 overlay: Uses overlay 0 2569 * 2 overlays: Uses Overlay 1 if MIRROR or DUAL HEAD 2570 * Uses Overlay 0 if SINGLE2 and not DUAL HEAD 2571 */ 2572 2573 if(pPriv->hasTwoOverlays) { 2574 2575 if((pPriv->dualHeadMode) || (pPriv->displayMode == DISPMODE_MIRROR)) { 2576 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, 0x01); 2577 } else { 2578 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0x01); 2579 } 2580 2581 } else if(pPriv->displayMode == DISPMODE_SINGLE2) { 2582 2583#ifdef SISDUALHEAD 2584 if(pPriv->dualHeadMode) { 2585 /* Check if overlay already grabbed by other head */ 2586 if(!(getsrreg(pSiS, 0x06) & 0x40)) return; 2587 } 2588#endif 2589 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0x01); 2590 2591 } 2592 2593 setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x01); 2594 2595 watchdog = WATCHDOG_DELAY; 2596 while((!vblank_active_CRT2(pSiS, pPriv)) && --watchdog); 2597 watchdog = WATCHDOG_DELAY; 2598 while(vblank_active_CRT2(pSiS, pPriv) && --watchdog); 2599 setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02); 2600 watchdog = WATCHDOG_DELAY; 2601 while((!vblank_active_CRT2(pSiS, pPriv)) && --watchdog); 2602 watchdog = WATCHDOG_DELAY; 2603 while(vblank_active_CRT2(pSiS, pPriv) && --watchdog); 2604 2605#ifdef SIS_CP 2606 SIS_CP_RESET_CP 2607#endif 2608 2609 } 2610 2611 if(pPriv->displayMode & (DISPMODE_SINGLE1 | DISPMODE_MIRROR)) { 2612 2613 /* CRT1: Always uses overlay 0 2614 */ 2615 2616#ifdef SISDUALHEAD 2617 if(pPriv->dualHeadMode) { 2618 if(!pPriv->hasTwoOverlays) { 2619 /* Check if overlay already grabbed by other head */ 2620 if(getsrreg(pSiS, 0x06) & 0x40) return; 2621 } 2622 } 2623#endif 2624 2625 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0x05); 2626 setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x01); 2627 2628 watchdog = WATCHDOG_DELAY; 2629 while((!vblank_active_CRT1(pSiS, pPriv)) && --watchdog); 2630 watchdog = WATCHDOG_DELAY; 2631 while(vblank_active_CRT1(pSiS, pPriv) && --watchdog); 2632 setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02); 2633 watchdog = WATCHDOG_DELAY; 2634 while((!vblank_active_CRT1(pSiS, pPriv)) && --watchdog); 2635 watchdog = WATCHDOG_DELAY; 2636 while(vblank_active_CRT1(pSiS, pPriv) && --watchdog); 2637 2638 } 2639} 2640 2641/********************************* 2642 * DisplayVideo() * 2643 *********************************/ 2644 2645static void 2646SISDisplayVideo(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) 2647{ 2648 SISPtr pSiS = SISPTR(pScrn); 2649#ifdef SISDUALHEAD 2650 SISEntPtr pSiSEnt = pSiS->entityPrivate; 2651#endif 2652 short srcPitch = pPriv->srcPitch; 2653 short height = pPriv->height; 2654 UShort screenwidth; 2655 SISOverlayRec overlay; 2656 int srcOffsetX = 0, srcOffsetY = 0; 2657 int sx = 0, sy = 0, watchdog; 2658 int index = 0, iscrt2 = 0; 2659#ifdef SISMERGED 2660 UChar temp; 2661 UShort screen2width = 0; 2662 int srcOffsetX2 = 0, srcOffsetY2 = 0; 2663 int sx2 = 0, sy2 = 0; 2664#endif 2665 2666 /* Determine whether we have two overlays or only one */ 2667 set_hastwooverlays(pSiS, pPriv); 2668 2669 pPriv->NoOverlay = FALSE; 2670#ifdef SISDUALHEAD 2671 if(pPriv->dualHeadMode) { 2672 if(!pPriv->hasTwoOverlays) { 2673 if(pSiS->SecondHead) { 2674 if(pSiSEnt->curxvcrtnum != 0) { 2675 if(pPriv->overlayStatus) { 2676 close_overlay(pSiS, pPriv); 2677 } 2678 pPriv->NoOverlay = TRUE; 2679 return; 2680 } 2681 } else { 2682 if(pSiSEnt->curxvcrtnum != 1) { 2683 if(pPriv->overlayStatus) { 2684 close_overlay(pSiS, pPriv); 2685 } 2686 pPriv->NoOverlay = TRUE; 2687 return; 2688 } 2689 } 2690 } 2691 } 2692#endif 2693 2694 /* setup dispmode (MIRROR, SINGLEx) */ 2695 set_dispmode(pScrn, pPriv); 2696 2697 /* Check if overlay is supported with current mode */ 2698#ifdef SISMERGED 2699 if(!pSiS->MergedFB) { 2700#endif 2701 if( ((pPriv->displayMode & DISPMODE_MIRROR) && 2702 ((pSiS->MiscFlags & (MISC_CRT1OVERLAY|MISC_CRT2OVERLAY)) != (MISC_CRT1OVERLAY|MISC_CRT2OVERLAY))) || 2703 ((pPriv->displayMode & DISPMODE_SINGLE1) && 2704 (!(pSiS->MiscFlags & MISC_CRT1OVERLAY))) || 2705 ((pPriv->displayMode & DISPMODE_SINGLE2) && 2706 (!(pSiS->MiscFlags & MISC_CRT2OVERLAY))) ) { 2707 if(pPriv->overlayStatus) { 2708 close_overlay(pSiS, pPriv); 2709 } 2710 pPriv->NoOverlay = TRUE; 2711 return; 2712 } 2713#ifdef SISMERGED 2714 } 2715#endif 2716 2717 memset(&overlay, 0, sizeof(overlay)); 2718 2719 overlay.pixelFormat = pPriv->id; 2720 overlay.pitch = overlay.origPitch = srcPitch; 2721 if(pPriv->usechromakey) { 2722 overlay.keyOP = (pPriv->insidechromakey) ? VI_ROP_ChromaKey : VI_ROP_NotChromaKey; 2723 } else { 2724 overlay.keyOP = VI_ROP_DestKey; 2725 } 2726 2727#ifdef SISDEINT 2728 switch(pPriv->deinterlacemethod) { 2729 case 1: 2730 overlay.bobEnable = 0x02; 2731 /* overlay.bobEnable |= (pPriv->currentBuf) ? 0x00 : 0x10; */ 2732 break; 2733 case 2: 2734 overlay.bobEnable = 0x08; 2735 /* overlay.bobEnable |= (pPriv->currentBuf) ? 0x00 : 0x10; */ 2736 break; 2737 case 3: 2738 overlay.bobEnable = 0x0a; 2739 /* overlay.bobEnable |= (pPriv->currentBuf) ? 0x00 : 0x10; */ 2740 break; 2741 default: 2742#endif 2743 overlay.bobEnable = 0x00; /* Disable BOB de-interlacer */ 2744#ifdef SISDEINT 2745 } 2746#endif 2747 2748#ifdef SISMERGED 2749 if(pSiS->MergedFB) { 2750 overlay.DoFirst = TRUE; 2751 overlay.DoSecond = TRUE; 2752 overlay.pitch2 = overlay.origPitch; 2753 overlay.currentmode = ((SiSMergedDisplayModePtr)pSiS->CurrentLayout.mode->Private)->CRT1; 2754 overlay.currentmode2 = ((SiSMergedDisplayModePtr)pSiS->CurrentLayout.mode->Private)->CRT2; 2755 overlay.SCREENheight = overlay.currentmode->VDisplay; 2756 overlay.SCREENheight2 = overlay.currentmode2->VDisplay; 2757 screenwidth = overlay.currentmode->HDisplay; 2758 screen2width = overlay.currentmode2->HDisplay; 2759 overlay.dstBox.x1 = pPriv->drw_x - pSiS->CRT1frameX0; 2760 overlay.dstBox.x2 = overlay.dstBox.x1 + pPriv->drw_w; 2761 overlay.dstBox.y1 = pPriv->drw_y - pSiS->CRT1frameY0; 2762 overlay.dstBox.y2 = overlay.dstBox.y1 + pPriv->drw_h; 2763 overlay.dstBox2.x1 = pPriv->drw_x - pSiS->CRT2pScrn->frameX0; 2764 overlay.dstBox2.x2 = overlay.dstBox2.x1 + pPriv->drw_w; 2765 overlay.dstBox2.y1 = pPriv->drw_y - pSiS->CRT2pScrn->frameY0; 2766 overlay.dstBox2.y2 = overlay.dstBox2.y1 + pPriv->drw_h; 2767 } else { 2768#endif 2769 overlay.currentmode = pSiS->CurrentLayout.mode; 2770 overlay.SCREENheight = overlay.currentmode->VDisplay; 2771 screenwidth = overlay.currentmode->HDisplay; 2772 overlay.dstBox.x1 = pPriv->drw_x - pScrn->frameX0; 2773 overlay.dstBox.x2 = pPriv->drw_x + pPriv->drw_w - pScrn->frameX0; 2774 overlay.dstBox.y1 = pPriv->drw_y - pScrn->frameY0; 2775 overlay.dstBox.y2 = pPriv->drw_y + pPriv->drw_h - pScrn->frameY0; 2776#ifdef SISMERGED 2777 } 2778#endif 2779 2780 /* Note: x2/y2 is actually real coordinate + 1 */ 2781 2782 if((overlay.dstBox.x1 >= overlay.dstBox.x2) || 2783 (overlay.dstBox.y1 >= overlay.dstBox.y2)) { 2784#ifdef SISMERGED 2785 if(pSiS->MergedFB) overlay.DoFirst = FALSE; 2786 else 2787#endif 2788 return; 2789 } 2790 2791 if((overlay.dstBox.x2 <= 0) || (overlay.dstBox.y2 <= 0)) { 2792#ifdef SISMERGED 2793 if(pSiS->MergedFB) overlay.DoFirst = FALSE; 2794 else 2795#endif 2796 return; 2797 } 2798 2799 if((overlay.dstBox.x1 >= screenwidth) || (overlay.dstBox.y1 >= overlay.SCREENheight)) { 2800#ifdef SISMERGED 2801 if(pSiS->MergedFB) overlay.DoFirst = FALSE; 2802 else 2803#endif 2804 return; 2805 } 2806 2807#ifdef SISMERGED 2808 if(pSiS->MergedFB) { 2809 /* Check if dotclock is within limits for CRT1 */ 2810 if(pPriv->displayMode & (DISPMODE_SINGLE1 | DISPMODE_MIRROR)) { 2811 if(!(pSiS->MiscFlags & MISC_CRT1OVERLAY)) { 2812 overlay.DoFirst = FALSE; 2813 } 2814 } 2815 } 2816#endif 2817 2818 if(overlay.dstBox.x1 < 0) { 2819 srcOffsetX = pPriv->src_w * (-overlay.dstBox.x1) / pPriv->drw_w; 2820 overlay.dstBox.x1 = 0; 2821 } 2822 if(overlay.dstBox.y1 < 0) { 2823 srcOffsetY = pPriv->src_h * (-overlay.dstBox.y1) / pPriv->drw_h; 2824 overlay.dstBox.y1 = 0; 2825 } 2826 2827 if((overlay.dstBox.x1 >= overlay.dstBox.x2 - 2) || 2828 (overlay.dstBox.x1 >= screenwidth - 2) || 2829 (overlay.dstBox.y1 >= overlay.dstBox.y2)) { 2830#ifdef SISMERGED 2831 if(pSiS->MergedFB) overlay.DoFirst = FALSE; 2832 else 2833#endif 2834 return; 2835 } 2836 2837#ifdef SISMERGED 2838 if(pSiS->MergedFB) { 2839 if((overlay.dstBox2.x2 <= 0) || (overlay.dstBox2.y2 <= 0)) 2840 overlay.DoSecond = FALSE; 2841 2842 if((overlay.dstBox2.x1 >= screen2width) || (overlay.dstBox2.y1 >= overlay.SCREENheight2)) 2843 overlay.DoSecond = FALSE; 2844 2845 if(overlay.dstBox2.x1 < 0) { 2846 srcOffsetX2 = pPriv->src_w * (-overlay.dstBox2.x1) / pPriv->drw_w; 2847 overlay.dstBox2.x1 = 0; 2848 } 2849 2850 if(overlay.dstBox2.y1 < 0) { 2851 srcOffsetY2 = pPriv->src_h * (-overlay.dstBox2.y1) / pPriv->drw_h; 2852 overlay.dstBox2.y1 = 0; 2853 } 2854 2855 if((overlay.dstBox2.x1 >= overlay.dstBox2.x2 - 2) || 2856 (overlay.dstBox2.x1 >= screen2width - 2) || 2857 (overlay.dstBox2.y1 >= overlay.dstBox2.y2)) 2858 overlay.DoSecond = FALSE; 2859 2860 /* Check if dotclock is within limits for CRT2 */ 2861 if(pPriv->displayMode & (DISPMODE_SINGLE2 | DISPMODE_MIRROR)) { 2862 if(!(pSiS->MiscFlags & MISC_CRT2OVERLAY)) { 2863 overlay.DoSecond = FALSE; 2864 } 2865 } 2866 2867 /* If neither overlay is to be displayed, disable them if they are currently enabled */ 2868 if((!overlay.DoFirst) && (!overlay.DoSecond)) { 2869 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0x05); 2870 setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x01); 2871 temp = getvideoreg(pSiS,Index_VI_Control_Misc0); 2872 if(temp & 0x02) { 2873 watchdog = WATCHDOG_DELAY; 2874 if(pPriv->hasTwoOverlays) { 2875 while((!vblank_active_CRT1(pSiS, pPriv)) && --watchdog); 2876 watchdog = WATCHDOG_DELAY; 2877 while(vblank_active_CRT1(pSiS, pPriv) && --watchdog); 2878 } else { 2879 temp = getsrreg(pSiS, 0x06); 2880 if(!(temp & 0x40)) { 2881 while((!vblank_active_CRT1(pSiS, pPriv)) && --watchdog); 2882 watchdog = WATCHDOG_DELAY; 2883 while(vblank_active_CRT1(pSiS, pPriv) && --watchdog); 2884 } else { 2885 while((!vblank_active_CRT2(pSiS, pPriv)) && --watchdog); 2886 watchdog = WATCHDOG_DELAY; 2887 while(vblank_active_CRT2(pSiS, pPriv) && --watchdog); 2888 } 2889 } 2890 setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02); 2891 } 2892 if(pPriv->hasTwoOverlays) { 2893 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, 0x01); 2894 setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x01); 2895 temp = getvideoreg(pSiS,Index_VI_Control_Misc0); 2896 if(temp & 0x02) { 2897 watchdog = WATCHDOG_DELAY; 2898 while((!vblank_active_CRT2(pSiS, pPriv)) && --watchdog); 2899 watchdog = WATCHDOG_DELAY; 2900 while(vblank_active_CRT2(pSiS, pPriv) && --watchdog); 2901 setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02); 2902 } 2903 } 2904 pPriv->overlayStatus = FALSE; 2905 return; 2906 } 2907 } 2908#endif 2909 2910 switch(pPriv->id) { 2911 2912 case PIXEL_FMT_YV12: 2913 overlay.planar = 1; 2914 overlay.planar_shiftpitch = 1; 2915#ifdef SISMERGED 2916 if((!pSiS->MergedFB) || (overlay.DoFirst)) { 2917#endif 2918 sx = (pPriv->src_x + srcOffsetX) & ~7; 2919 sy = (pPriv->src_y + srcOffsetY) & ~1; 2920 overlay.PSY = pPriv->bufAddr[pPriv->currentBuf] + sx + sy*srcPitch; 2921 overlay.PSV = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch + ((sx + sy*srcPitch/2) >> 1); 2922 overlay.PSU = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch*5/4 + ((sx + sy*srcPitch/2) >> 1); 2923 overlay.PSY += FBOFFSET; 2924 overlay.PSV += FBOFFSET; 2925 overlay.PSU += FBOFFSET; 2926 overlay.PSY >>= pPriv->shiftValue; 2927 overlay.PSV >>= pPriv->shiftValue; 2928 overlay.PSU >>= pPriv->shiftValue; 2929#ifdef SISMERGED 2930 } 2931 if((pSiS->MergedFB) && (overlay.DoSecond)) { 2932 sx2 = (pPriv->src_x + srcOffsetX2) & ~7; 2933 sy2 = (pPriv->src_y + srcOffsetY2) & ~1; 2934 overlay.PSY2 = pPriv->bufAddr[pPriv->currentBuf] + sx2 + sy2*srcPitch; 2935 overlay.PSV2 = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch + ((sx2 + sy2*srcPitch/2) >> 1); 2936 overlay.PSU2 = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch*5/4 + ((sx2 + sy2*srcPitch/2) >> 1); 2937 overlay.PSY2 += FBOFFSET; 2938 overlay.PSV2 += FBOFFSET; 2939 overlay.PSU2 += FBOFFSET; 2940 overlay.PSY2 >>= pPriv->shiftValue; 2941 overlay.PSV2 >>= pPriv->shiftValue; 2942 overlay.PSU2 >>= pPriv->shiftValue; 2943 } 2944#endif 2945 break; 2946 2947 case PIXEL_FMT_I420: 2948 overlay.planar = 1; 2949 overlay.planar_shiftpitch = 1; 2950#ifdef SISMERGED 2951 if((!pSiS->MergedFB) || (overlay.DoFirst)) { 2952#endif 2953 sx = (pPriv->src_x + srcOffsetX) & ~7; 2954 sy = (pPriv->src_y + srcOffsetY) & ~1; 2955 overlay.PSY = pPriv->bufAddr[pPriv->currentBuf] + sx + sy*srcPitch; 2956 overlay.PSV = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch*5/4 + ((sx + sy*srcPitch/2) >> 1); 2957 overlay.PSU = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch + ((sx + sy*srcPitch/2) >> 1); 2958 overlay.PSY += FBOFFSET; 2959 overlay.PSV += FBOFFSET; 2960 overlay.PSU += FBOFFSET; 2961 overlay.PSY >>= pPriv->shiftValue; 2962 overlay.PSV >>= pPriv->shiftValue; 2963 overlay.PSU >>= pPriv->shiftValue; 2964#ifdef SISMERGED 2965 } 2966 if((pSiS->MergedFB) && (overlay.DoSecond)) { 2967 sx2 = (pPriv->src_x + srcOffsetX2) & ~7; 2968 sy2 = (pPriv->src_y + srcOffsetY2) & ~1; 2969 overlay.PSY2 = pPriv->bufAddr[pPriv->currentBuf] + sx2 + sy2*srcPitch; 2970 overlay.PSV2 = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch*5/4 + ((sx2 + sy2*srcPitch/2) >> 1); 2971 overlay.PSU2 = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch + ((sx2 + sy2*srcPitch/2) >> 1); 2972 overlay.PSY2 += FBOFFSET; 2973 overlay.PSV2 += FBOFFSET; 2974 overlay.PSU2 += FBOFFSET; 2975 overlay.PSY2 >>= pPriv->shiftValue; 2976 overlay.PSV2 >>= pPriv->shiftValue; 2977 overlay.PSU2 >>= pPriv->shiftValue; 2978 } 2979#endif 2980 break; 2981 2982 case PIXEL_FMT_NV12: 2983 case PIXEL_FMT_NV21: 2984 overlay.planar = 1; 2985 overlay.planar_shiftpitch = 0; 2986#ifdef SISMERGED 2987 if((!pSiS->MergedFB) || (overlay.DoFirst)) { 2988#endif 2989 sx = (pPriv->src_x + srcOffsetX) & ~7; 2990 sy = (pPriv->src_y + srcOffsetY) & ~1; 2991 overlay.PSY = pPriv->bufAddr[pPriv->currentBuf] + sx + sy*srcPitch; 2992 overlay.PSV = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch + ((sx + sy*srcPitch/2) >> 1); 2993 overlay.PSY += FBOFFSET; 2994 overlay.PSV += FBOFFSET; 2995 overlay.PSY >>= pPriv->shiftValue; 2996 overlay.PSV >>= pPriv->shiftValue; 2997 overlay.PSU = overlay.PSV; 2998#ifdef SISMERGED 2999 } 3000 if((pSiS->MergedFB) && (overlay.DoSecond)) { 3001 sx2 = (pPriv->src_x + srcOffsetX2) & ~7; 3002 sy2 = (pPriv->src_y + srcOffsetY2) & ~1; 3003 overlay.PSY2 = pPriv->bufAddr[pPriv->currentBuf] + sx2 + sy2*srcPitch; 3004 overlay.PSV2 = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch + ((sx2 + sy2*srcPitch/2) >> 1); 3005 overlay.PSY2 += FBOFFSET; 3006 overlay.PSV2 += FBOFFSET; 3007 overlay.PSY2 >>= pPriv->shiftValue; 3008 overlay.PSV2 >>= pPriv->shiftValue; 3009 overlay.PSU2 = overlay.PSV2; 3010 } 3011#endif 3012 break; 3013 3014 case PIXEL_FMT_YUY2: 3015 case PIXEL_FMT_UYVY: 3016 case PIXEL_FMT_YVYU: 3017 case PIXEL_FMT_RGB6: 3018 case PIXEL_FMT_RGB5: 3019 default: 3020 overlay.planar = 0; 3021#ifdef SISMERGED 3022 if((!pSiS->MergedFB) || (overlay.DoFirst)) { 3023#endif 3024 sx = (pPriv->src_x + srcOffsetX) & ~1; 3025 sy = (pPriv->src_y + srcOffsetY); 3026 overlay.PSY = (pPriv->bufAddr[pPriv->currentBuf] + sx*2 + sy*srcPitch); 3027 overlay.PSY += FBOFFSET; 3028 overlay.PSY >>= pPriv->shiftValue; 3029#ifdef SISMERGED 3030 } 3031 if((pSiS->MergedFB) && (overlay.DoSecond)) { 3032 sx2 = (pPriv->src_x + srcOffsetX2) & ~1; 3033 sy2 = (pPriv->src_y + srcOffsetY2); 3034 overlay.PSY2 = (pPriv->bufAddr[pPriv->currentBuf] + sx2*2 + sy2*srcPitch); 3035 overlay.PSY2 += FBOFFSET; 3036 overlay.PSY2 >>= pPriv->shiftValue; 3037 } 3038#endif 3039 break; 3040 } 3041 3042 /* Some clipping checks */ 3043#ifdef SISMERGED 3044 if((!pSiS->MergedFB) || (overlay.DoFirst)) { 3045#endif 3046 overlay.srcW = pPriv->src_w - (sx - pPriv->src_x); 3047 overlay.srcH = pPriv->src_h - (sy - pPriv->src_y); 3048 if( (pPriv->oldx1 != overlay.dstBox.x1) || 3049 (pPriv->oldx2 != overlay.dstBox.x2) || 3050 (pPriv->oldy1 != overlay.dstBox.y1) || 3051 (pPriv->oldy2 != overlay.dstBox.y2) ) { 3052 pPriv->mustwait = 1; 3053 pPriv->oldx1 = overlay.dstBox.x1; pPriv->oldx2 = overlay.dstBox.x2; 3054 pPriv->oldy1 = overlay.dstBox.y1; pPriv->oldy2 = overlay.dstBox.y2; 3055 } 3056#ifdef SISMERGED 3057 } 3058 if((pSiS->MergedFB) && (overlay.DoSecond)) { 3059 overlay.srcW2 = pPriv->src_w - (sx2 - pPriv->src_x); 3060 overlay.srcH2 = pPriv->src_h - (sy2 - pPriv->src_y); 3061 if( (pPriv->oldx1_2 != overlay.dstBox2.x1) || 3062 (pPriv->oldx2_2 != overlay.dstBox2.x2) || 3063 (pPriv->oldy1_2 != overlay.dstBox2.y1) || 3064 (pPriv->oldy2_2 != overlay.dstBox2.y2) ) { 3065 pPriv->mustwait = 1; 3066 pPriv->oldx1_2 = overlay.dstBox2.x1; pPriv->oldx2_2 = overlay.dstBox2.x2; 3067 pPriv->oldy1_2 = overlay.dstBox2.y1; pPriv->oldy2_2 = overlay.dstBox2.y2; 3068 } 3069 } 3070#endif 3071 3072#ifdef SISMERGED 3073 /* Disable an overlay if it is not to be displayed (but enabled currently) */ 3074 if((pSiS->MergedFB) && (pPriv->hasTwoOverlays)) { 3075 if(!overlay.DoFirst) { 3076 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0x05); 3077 setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x01); 3078 temp = getvideoreg(pSiS,Index_VI_Control_Misc0); 3079 if(temp & 0x02) { 3080 watchdog = WATCHDOG_DELAY; 3081 while((!vblank_active_CRT1(pSiS, pPriv)) && --watchdog); 3082 watchdog = WATCHDOG_DELAY; 3083 while(vblank_active_CRT1(pSiS, pPriv) && --watchdog); 3084 setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02); 3085 } 3086 } else if(!overlay.DoSecond) { 3087 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, 0x01); 3088 setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x01); 3089 temp = getvideoreg(pSiS,Index_VI_Control_Misc0); 3090 if(temp & 0x02) { 3091 watchdog = WATCHDOG_DELAY; 3092 while((!vblank_active_CRT2(pSiS, pPriv)) && --watchdog); 3093 watchdog = WATCHDOG_DELAY; 3094 while(vblank_active_CRT2(pSiS, pPriv) && --watchdog); 3095 setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02); 3096 } 3097 } 3098 } 3099#endif 3100 3101 /* Loop head */ 3102 /* Note: index can only be 1 for CRT2, ie overlay 1 3103 * is only used for CRT2. 3104 */ 3105 if(pPriv->displayMode & DISPMODE_SINGLE2) { 3106 if(pPriv->hasTwoOverlays) { /* We have 2 overlays: */ 3107 if(pPriv->dualHeadMode) { 3108 /* Dual head: We use overlay 2 for CRT2 */ 3109 index = 1; iscrt2 = 1; 3110 } else { 3111 /* Single head: We use overlay 1 for CRT2 */ 3112 index = 0; iscrt2 = 1; 3113 } 3114 } else { /* We have 1 overlay */ 3115 /* We use that only overlay for CRT2 */ 3116 index = 0; iscrt2 = 1; 3117 } 3118 overlay.VBlankActiveFunc = vblank_active_CRT2; 3119#ifdef SISMERGED 3120 if(!pPriv->hasTwoOverlays) { 3121 if((pSiS->MergedFB) && (!overlay.DoSecond)) { 3122 index = 0; iscrt2 = 0; 3123 overlay.VBlankActiveFunc = vblank_active_CRT1; 3124 pPriv->displayMode = DISPMODE_SINGLE1; 3125 } 3126 } 3127#endif 3128 } else { 3129 index = 0; iscrt2 = 0; 3130 overlay.VBlankActiveFunc = vblank_active_CRT1; 3131#ifdef SISMERGED 3132 if((pSiS->MergedFB) && (!overlay.DoFirst)) { 3133 if(pPriv->hasTwoOverlays) index = 1; 3134 iscrt2 = 1; 3135 overlay.VBlankActiveFunc = vblank_active_CRT2; 3136 if(!pPriv->hasTwoOverlays) { 3137 pPriv->displayMode = DISPMODE_SINGLE2; 3138 } 3139 } 3140#endif 3141 } 3142 3143 /* set display mode SR06,32 (CRT1, CRT2 or mirror) */ 3144 set_disptype_regs(pScrn, pPriv); 3145 3146 /* set (not only calc) merge line buffer */ 3147#ifdef SISMERGED 3148 if(!pSiS->MergedFB) { 3149#endif 3150 merge_line_buf(pSiS, pPriv, (overlay.srcW > pPriv->linebufMergeLimit), overlay.srcW, 3151 pPriv->linebufMergeLimit); 3152#ifdef SISMERGED 3153 } else { 3154 Bool temp1 = FALSE, temp2 = FALSE; 3155 if(overlay.DoFirst) { 3156 if(overlay.srcW > pPriv->linebufMergeLimit) temp1 = TRUE; 3157 } 3158 if(overlay.DoSecond) { 3159 if(overlay.srcW2 > pPriv->linebufMergeLimit) temp2 = TRUE; 3160 } 3161 merge_line_buf_mfb(pSiS, pPriv, temp1, temp2, overlay.srcW, overlay.srcW2, 3162 pPriv->linebufMergeLimit); 3163 } 3164#endif 3165 3166 /* calculate (not set!) line buffer length */ 3167#ifdef SISMERGED 3168 if((!pSiS->MergedFB) || (overlay.DoFirst)) 3169#endif 3170 calc_line_buf_size_1(&overlay, pPriv); 3171#ifdef SISMERGED 3172 if((pSiS->MergedFB) && (overlay.DoSecond)) 3173 calc_line_buf_size_2(&overlay, pPriv); 3174#endif 3175 3176 if(pPriv->dualHeadMode) { 3177#ifdef SISDUALHEAD 3178 if(!pSiS->SecondHead) { 3179 if(pPriv->updatetvxpos) { 3180 SiS_SetTVxposoffset(pScrn, pPriv->tvxpos); 3181 pPriv->updatetvxpos = FALSE; 3182 } 3183 if(pPriv->updatetvypos) { 3184 SiS_SetTVyposoffset(pScrn, pPriv->tvypos); 3185 pPriv->updatetvypos = FALSE; 3186 } 3187 } 3188#endif 3189 } else { 3190 if(pPriv->updatetvxpos) { 3191 SiS_SetTVxposoffset(pScrn, pPriv->tvxpos); 3192 pPriv->updatetvxpos = FALSE; 3193 } 3194 if(pPriv->updatetvypos) { 3195 SiS_SetTVyposoffset(pScrn, pPriv->tvypos); 3196 pPriv->updatetvypos = FALSE; 3197 } 3198 } 3199 3200#if 0 /* Clearing this does not seem to be required */ 3201 /* and might even be dangerous. */ 3202 if(pSiS->VGAEngine == SIS_315_VGA) { 3203 watchdog = WATCHDOG_DELAY; 3204 while(overlay.VBlankActiveFunc(pSiS, pPriv) && --watchdog); 3205 setvideoregmask(pSiS, Index_VI_Control_Misc3, 0x00, 0x03); 3206 } 3207#endif 3208 setvideoregmask(pSiS, Index_VI_Control_Misc3, 0x03, 0x03); 3209 3210 /* Do the following in a loop for CRT1 and CRT2 ----------------- */ 3211MIRROR: 3212 3213 /* calculate scale factor */ 3214#ifdef SISMERGED 3215 if(pSiS->MergedFB && iscrt2) 3216 calc_scale_factor_2(&overlay, pScrn, pPriv, index, iscrt2); 3217 else 3218#endif 3219 calc_scale_factor(&overlay, pScrn, pPriv, index, iscrt2); 3220 3221 /* Select overlay 0 (used for CRT1/or CRT2) or overlay 1 (used for CRT2 only) */ 3222 setvideoregmask(pSiS, Index_VI_Control_Misc2, index, 0x01); 3223 3224 /* set format (before color and chroma keys) */ 3225 set_format(pSiS, &overlay); 3226 3227 /* set color key */ 3228 set_colorkey(pSiS, pPriv->colorKey); 3229 3230 if(pPriv->usechromakey) { 3231 /* Select chroma key format (300 series only) */ 3232 if(pSiS->VGAEngine == SIS_300_VGA) { 3233 setvideoregmask(pSiS, Index_VI_Control_Misc0, 3234 (pPriv->yuvchromakey ? 0x40 : 0x00), 0x40); 3235 } 3236 set_chromakey(pSiS, pPriv->chromamin, pPriv->chromamax); 3237 } 3238 3239 /* set brightness, contrast, hue, saturation */ 3240 set_brightness(pSiS, pPriv->brightness); 3241 set_contrast(pSiS, pPriv->contrast); 3242 if(pSiS->VGAEngine == SIS_315_VGA) { 3243 set_hue(pSiS, pPriv->hue); 3244 set_saturation(pSiS, pPriv->saturation); 3245 } 3246 3247 /* enable/disable graphics display around overlay 3248 * (Since disabled overlays don't get treated in this 3249 * loop, we omit respective checks here) 3250 */ 3251 if(!iscrt2) { 3252 set_disablegfx(pSiS, pPriv->disablegfx, &overlay); 3253 } else if(!pSiS->hasTwoOverlays) { 3254 set_disablegfx(pSiS, FALSE, &overlay); 3255 } 3256 set_disablegfxlr(pSiS, pPriv->disablegfxlr, &overlay); 3257 3258#ifdef SIS_CP 3259 SIS_CP_VIDEO_SET_CP 3260#endif 3261 3262 /* set remaining overlay parameters */ 3263 set_overlay(pSiS, &overlay, pPriv, index, iscrt2); 3264 3265 /* enable overlay */ 3266 setvideoregmask (pSiS, Index_VI_Control_Misc0, 0x02, 0x02); 3267 3268 /* loop foot */ 3269 if(pPriv->displayMode & DISPMODE_MIRROR && 3270 index == 0 && 3271 pPriv->hasTwoOverlays) { 3272#ifdef SISMERGED 3273 if((!pSiS->MergedFB) || overlay.DoSecond) { 3274#endif 3275 index = 1; iscrt2 = 1; 3276 overlay.VBlankActiveFunc = vblank_active_CRT2; 3277 goto MIRROR; 3278#ifdef SISMERGED 3279 } 3280#endif 3281 } 3282 3283 /* Now for the trigger: This is a bad hack to work-around 3284 * an obvious hardware bug: Overlay 1 (which is ONLY used 3285 * for CRT2 in this driver) does not always update its 3286 * window position and some other stuff. Earlier, this was 3287 * solved be disabling the overlay, but this took forever 3288 * and was ugly on the screen. 3289 * Now: We write 0x03 to 0x74 from the beginning. This is 3290 * meant as a "lock" - the driver is supposed to write 0 3291 * to this register, bit 0 for overlay 0, bit 1 for over- 3292 * lay 1, then change buffer addresses, pitches, window 3293 * position, scaler registers, format, etc., then write 3294 * 1 to 0x74. The hardware then reads the registers into 3295 * its internal engine and clears these bits. 3296 * All this works for overlay 0, but not 1. Overlay 1 3297 * has assumingly the following restrictions: 3298 * - New data written to the registers is only read 3299 * correctly by the engine if the registers are written 3300 * when the current scanline is beyond the current 3301 * overlay position and below the maximum visible 3302 * scanline (vertical screen resolution) 3303 * - If a vertical retrace occures during writing the 3304 * registers, the registers written BEFORE this re- 3305 * trace happened, are not being read into the 3306 * engine if the trigger is set after the retrace. 3307 * Therefore: We write the overlay registers above in 3308 * set_overlay only if the scanline matches, and save 3309 * the then current scanline. If this scanline is higher 3310 * than the now current scanline, we assume a retrace, 3311 * wait for the scanline to match the criteria above again, 3312 * and rewrite all relevant registers. 3313 * I have no idea if this is meant that way, but after 3314 * fiddling three entire days with this crap, I found this 3315 * to be the only solution. 3316 */ 3317 if(pSiS->VGAEngine == SIS_315_VGA) { 3318 if((pPriv->mustwait) && index) { 3319 watchdog = get_scanline_CRT2(pSiS, pPriv); 3320 if(watchdog <= overlay.oldLine) { 3321 int i, mytop = overlay.oldtop; 3322 int screenHeight = overlay.SCREENheight; 3323#ifdef SISMERGED 3324 if(pSiS->MergedFB) { 3325 screenHeight = overlay.SCREENheight2; 3326 } 3327#endif 3328 if(mytop < screenHeight - 2) { 3329 do { 3330 watchdog = get_scanline_CRT2(pSiS, pPriv); 3331 } while((watchdog <= mytop) || (watchdog >= screenHeight)); 3332 } 3333 for(i=0x02; i<=0x12; i++) { 3334 setvideoreg(pSiS, i, getvideoreg(pSiS, i)); 3335 } 3336 for(i=0x18; i<=0x1c; i++) { 3337 setvideoreg(pSiS, i, getvideoreg(pSiS, i)); 3338 } 3339 for(i=0x2c; i<=0x2e; i++) { 3340 setvideoreg(pSiS, i, getvideoreg(pSiS, i)); 3341 } 3342 for(i=0x6b; i<=0x6f; i++) { 3343 setvideoreg(pSiS, i, getvideoreg(pSiS, i)); 3344 } 3345 } 3346 } 3347 /* Trigger register copy for 315/330 series */ 3348 setvideoregmask(pSiS, Index_VI_Control_Misc3, 0x03, 0x03); 3349 } 3350 3351 pPriv->mustwait = 0; 3352 pPriv->overlayStatus = TRUE; 3353} 3354 3355/********************************* 3356 * Memory management * 3357 *********************************/ 3358 3359#ifdef SIS_USE_EXA 3360static void 3361SiSDestroyArea(ScreenPtr pScreen, ExaOffscreenArea *area) 3362{ 3363 void **handle = (void *)area->privData; 3364 *handle = NULL; 3365} 3366#endif 3367 3368unsigned int 3369SISAllocateFBMemory( 3370 ScrnInfoPtr pScrn, 3371 void **handle, 3372 int bytesize 3373){ 3374 SISPtr pSiS = SISPTR(pScrn); 3375 ScreenPtr pScreen = xf86ScrnToScreen(pScrn); 3376 3377#ifdef SIS_USE_XAA 3378 if(!pSiS->useEXA) { 3379 FBLinearPtr linear = (FBLinearPtr)(*handle); 3380 FBLinearPtr new_linear; 3381 int depth = pSiS->CurrentLayout.bitsPerPixel >> 3; 3382 int size = ((bytesize + depth - 1) / depth); 3383 3384 if(linear) { 3385 if(linear->size >= size) { 3386 return (unsigned int)(linear->offset * depth); 3387 } 3388 3389 if(xf86ResizeOffscreenLinear(linear, size)) { 3390 return (unsigned int)(linear->offset * depth); 3391 } 3392 3393 xf86FreeOffscreenLinear(linear); 3394 *handle = NULL; 3395 } 3396 3397 new_linear = xf86AllocateOffscreenLinear(pScreen, size, 8, NULL, NULL, NULL); 3398 3399 if(!new_linear) { 3400 int max_size; 3401 3402 xf86QueryLargestOffscreenLinear(pScreen, &max_size, 8, PRIORITY_EXTREME); 3403 3404 if(max_size < size) 3405 return 0; 3406 3407 xf86PurgeUnlockedOffscreenAreas(pScreen); 3408 new_linear = xf86AllocateOffscreenLinear(pScreen, size, 8, NULL, NULL, NULL); 3409 } 3410 if(!new_linear) { 3411 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3412 "Xv: Failed to allocate %d pixels of linear video memory\n", size); 3413 return 0; 3414 } else { 3415 *handle = (void *)new_linear; 3416 return (unsigned int)(new_linear->offset * depth); 3417 } 3418 } 3419#endif 3420#ifdef SIS_USE_EXA 3421 if(pSiS->useEXA && !pSiS->NoAccel) { 3422 ExaOffscreenArea *area = (ExaOffscreenArea *)(*handle); 3423 3424 if(area) { 3425 if(area->size >= bytesize) return (unsigned int)(area->offset); 3426 3427 exaOffscreenFree(pScreen, area); 3428 *handle = NULL; 3429 } 3430 3431 if(!(area = exaOffscreenAlloc(pScreen, bytesize, 8, TRUE, SiSDestroyArea, (pointer)handle))) { 3432 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3433 "Xv: Failed to allocate %d bytes of video memory\n", bytesize); 3434 return 0; 3435 } else { 3436 *handle = (void *)area; 3437 return (unsigned int)(area->offset); 3438 } 3439 } 3440#endif 3441 3442 return 0; 3443} 3444 3445void 3446SISFreeFBMemory(ScrnInfoPtr pScrn, void **handle) 3447{ 3448 SISPtr pSiS = SISPTR(pScrn); 3449#ifdef SIS_USE_EXA 3450 ScreenPtr pScreen = xf86ScrnToScreen(pScrn); 3451#endif 3452 3453#ifdef SIS_USE_XAA 3454 if(!pSiS->useEXA) { 3455 if(*handle) { 3456 xf86FreeOffscreenLinear((FBLinearPtr)(*handle)); 3457 } 3458 } 3459#endif 3460#ifdef SIS_USE_EXA 3461 if(pSiS->useEXA && !pSiS->NoAccel) { 3462 if(*handle) { 3463 exaOffscreenFree(pScreen, (ExaOffscreenArea *)(*handle)); 3464 } 3465 } 3466#endif 3467 *handle = NULL; 3468} 3469 3470/********************************* 3471 * StopVideo() * 3472 *********************************/ 3473 3474static void 3475SISStopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown) 3476{ 3477 SISPortPrivPtr pPriv = (SISPortPrivPtr)data; 3478 SISPtr pSiS = SISPTR(pScrn); 3479 3480 if(pPriv->grabbedByV4L) return; 3481 3482 REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 3483 3484 if(shutdown) { 3485 if(pPriv->videoStatus & CLIENT_VIDEO_ON) { 3486 close_overlay(pSiS, pPriv); 3487 pPriv->mustwait = 1; 3488 } 3489 SISFreeFBMemory(pScrn, &pPriv->handle); 3490 pPriv->videoStatus = 0; 3491 } else { 3492 if(pPriv->videoStatus & CLIENT_VIDEO_ON) { 3493 UpdateCurrentTime(); 3494 pPriv->offTime = currentTime.milliseconds + OFF_DELAY; 3495 pPriv->videoStatus = OFF_TIMER | CLIENT_VIDEO_ON; 3496 pSiS->VideoTimerCallback = SISVideoTimerCallback; 3497 } 3498 } 3499} 3500 3501/********************************* 3502 * PutImage() * 3503 *********************************/ 3504 3505static int 3506SISPutImage( 3507 ScrnInfoPtr pScrn, 3508 short src_x, short src_y, 3509 short drw_x, short drw_y, 3510 short src_w, short src_h, 3511 short drw_w, short drw_h, 3512 int id, UChar *buf, 3513 short width, short height, 3514 Bool sync, 3515 RegionPtr clipBoxes, pointer data, 3516 DrawablePtr pDraw 3517){ 3518 SISPtr pSiS = SISPTR(pScrn); 3519 SISPortPrivPtr pPriv = (SISPortPrivPtr)data; 3520#ifdef SIS_USE_XAA 3521 XAAInfoRecPtr pXAA = pSiS->AccelInfoPtr; 3522 int depth = pSiS->CurrentLayout.bitsPerPixel >> 3; 3523 int myreds[] = { 0x000000ff, 0x0000f800, 0, 0x00ff0000 }; 3524#endif 3525 int totalSize = 0; 3526#ifdef SISDEINT 3527 Bool deintfm = (pPriv->deinterlacemethod > 1) ? TRUE : FALSE; 3528#endif 3529 3530#if 0 3531 xf86DrvMsg(0, X_INFO, "PutImage: src %dx%d-%dx%d, drw %dx%d-%dx%d, id %x, w %d h %d, buf %p\n", 3532 src_x, src_y, src_w, src_h, drw_x, drw_y, drw_w, drw_h, id, width, height, buf); 3533#endif 3534 3535 if(pPriv->grabbedByV4L) return Success; 3536 3537 pPriv->drw_x = drw_x; 3538 pPriv->drw_y = drw_y; 3539 pPriv->drw_w = drw_w; 3540 pPriv->drw_h = drw_h; 3541 pPriv->src_x = src_x; 3542 pPriv->src_y = src_y; 3543 pPriv->src_w = src_w; 3544 pPriv->src_h = src_h; 3545 pPriv->id = id; 3546 pPriv->height = height; 3547 3548 /* Pixel formats: 3549 1. YU12: 3 planes: H V 3550 Y sample period 1 1 (8 bit per pixel) 3551 V sample period 2 2 (8 bit per pixel, subsampled) 3552 U sample period 2 2 (8 bit per pixel, subsampled) 3553 3554 Y plane is fully sampled (width*height), U and V planes 3555 are sampled in 2x2 blocks, hence a group of 4 pixels requires 3556 4 + 1 + 1 = 6 bytes. The data is planar, ie in single planes 3557 for Y, U and V. 3558 2. UYVY: 3 planes: H V 3559 Y sample period 1 1 (8 bit per pixel) 3560 V sample period 2 1 (8 bit per pixel, subsampled) 3561 U sample period 2 1 (8 bit per pixel, subsampled) 3562 Y plane is fully sampled (width*height), U and V planes 3563 are sampled in 2x1 blocks, hence a group of 4 pixels requires 3564 4 + 2 + 2 = 8 bytes. The data is bit packed, there are no separate 3565 Y, U or V planes. 3566 Bit order: U0 Y0 V0 Y1 U2 Y2 V2 Y3 ... 3567 3. I420: Like YU12, but planes U and V are in reverse order. 3568 4. YUY2: Like UYVY, but order is 3569 Y0 U0 Y1 V0 Y2 U2 Y3 V2 ... 3570 5. YVYU: Like YUY2, but order is 3571 Y0 V0 Y1 U0 Y2 V2 Y3 U2 ... 3572 6. NV12, NV21: 2 planes H V 3573 Y sample period 1 1 (8 bit per pixel) 3574 V sample period 2 1 (8 bit per pixel, subsampled) 3575 U sample period 2 1 (8 bit per pixel, subsampled) 3576 Y plane is fully samples (width*height), U and V planes are 3577 interleaved in memory (one byte U, one byte V for NV12, NV21 3578 other way round) and sampled in 2x1 blocks. Otherwise such 3579 as all other planar formats. 3580 */ 3581 3582 switch(id){ 3583 case PIXEL_FMT_YV12: 3584 case PIXEL_FMT_I420: 3585 case PIXEL_FMT_NV12: 3586 case PIXEL_FMT_NV21: 3587 pPriv->srcPitch = (width + 7) & ~7; 3588 /* Size = width * height * 3 / 2 */ 3589 totalSize = (pPriv->srcPitch * height * 3) >> 1; /* Verified */ 3590 break; 3591 case PIXEL_FMT_YUY2: 3592 case PIXEL_FMT_UYVY: 3593 case PIXEL_FMT_YVYU: 3594 case PIXEL_FMT_RGB6: 3595 case PIXEL_FMT_RGB5: 3596 default: 3597 pPriv->srcPitch = ((width << 1) + 3) & ~3; /* Verified */ 3598 /* Size = width * 2 * height */ 3599 totalSize = pPriv->srcPitch * height; 3600 } 3601 3602 /* make it a multiple of 16 to simplify to copy loop */ 3603 totalSize += 15; 3604 totalSize &= ~15; /* in bytes */ 3605 3606 /* allocate memory (we do doublebuffering) - size is in bytes */ 3607 if(!(pPriv->bufAddr[0] = SISAllocateFBMemory(pScrn, &pPriv->handle, totalSize << 1))) 3608 return BadAlloc; 3609 3610#ifdef SISDEINT 3611 if(deintfm) { 3612 pPriv->bufAddr[1] = pPriv->bufAddr[0] + pPriv->srcPitch; 3613 3614 { 3615 CARD8 *src = (CARD8 *)buf; 3616 CARD8 *dest = (CARD8 *)(pSiS->FbBase + pPriv->bufAddr[pPriv->currentBuf]); 3617 int i = height; 3618 while(i--) { 3619 SiSMemCopyToVideoRam(pSiS, dest, src, pPriv->srcPitch); 3620 src += pPriv->srcPitch; 3621 dest += (pPriv->srcPitch << 1); 3622 } 3623 } 3624 3625 } else { 3626#endif 3627 pPriv->bufAddr[1] = pPriv->bufAddr[0] + totalSize; 3628 3629 /* copy data */ 3630 if((pSiS->XvUseMemcpy) || (totalSize < 16)) { 3631 SiSMemCopyToVideoRam(pSiS, pSiS->FbBase + pPriv->bufAddr[pPriv->currentBuf], buf, totalSize); 3632 } else { 3633 ULong i; 3634 CARD32 *src = (CARD32 *)buf; 3635 CARD32 *dest = (CARD32 *)(pSiS->FbBase + pPriv->bufAddr[pPriv->currentBuf]); 3636 for(i = 0; i < (totalSize/16); i++) { 3637 *dest++ = *src++; 3638 *dest++ = *src++; 3639 *dest++ = *src++; 3640 *dest++ = *src++; 3641 } 3642 } 3643#ifdef SISDEINT 3644 } 3645#endif 3646 3647 SISDisplayVideo(pScrn, pPriv); 3648 3649 /* update cliplist */ 3650 if(pPriv->autopaintColorKey && 3651 (pPriv->grabbedByV4L || 3652#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,3,99,3,0) 3653 (!RegionsEqual(&pPriv->clip, clipBoxes)) || 3654#else 3655 (!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) || 3656#endif 3657 (pPriv->PrevOverlay != pPriv->NoOverlay))) { 3658 /* We always paint the colorkey for V4L */ 3659 if(!pPriv->grabbedByV4L) { 3660 REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes); 3661 } 3662 /* draw these */ 3663 pPriv->PrevOverlay = pPriv->NoOverlay; 3664#ifdef SIS_USE_XAA 3665 if((pPriv->NoOverlay) && pXAA && pXAA->FillMono8x8PatternRects) { 3666 (*pXAA->FillMono8x8PatternRects)(pScrn, myreds[depth-1], 3667 0x000000, GXcopy, ~0, 3668 REGION_NUM_RECTS(clipBoxes), 3669 REGION_RECTS(clipBoxes), 3670 0x00422418, 0x18244200, 0, 0); 3671 } else { 3672#endif 3673 if(!pSiS->disablecolorkeycurrent) { 3674#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,1,99,1,0) 3675 (*pXAA->FillSolidRects)(pScrn, pPriv->colorKey, GXcopy, ~0, 3676 REGION_NUM_RECTS(clipBoxes), 3677 REGION_RECTS(clipBoxes)); 3678#else 3679 xf86XVFillKeyHelper(pScrn->pScreen, (pPriv->NoOverlay) ? 0x00ff0000 : pPriv->colorKey, clipBoxes); 3680#endif 3681 } 3682#ifdef SIS_USE_XAA 3683 } 3684#endif 3685 3686 } 3687 3688 pPriv->currentBuf ^= 1; 3689 3690 pPriv->videoStatus = CLIENT_VIDEO_ON; 3691 3692 pSiS->VideoTimerCallback = SISVideoTimerCallback; 3693 3694 return Success; 3695} 3696 3697/********************************* 3698 * QueryImageAttributes() * 3699 *********************************/ 3700 3701static int 3702SISQueryImageAttributes( 3703 ScrnInfoPtr pScrn, 3704 int id, 3705 UShort *w, UShort *h, 3706 int *pitches, int *offsets 3707){ 3708 int pitchY, pitchUV; 3709 int size, sizeY, sizeUV; 3710 3711 if(*w < IMAGE_MIN_WIDTH) *w = IMAGE_MIN_WIDTH; 3712 if(*h < IMAGE_MIN_HEIGHT) *h = IMAGE_MIN_HEIGHT; 3713 3714 if(*w > DummyEncoding.width) *w = DummyEncoding.width; 3715 if(*h > DummyEncoding.height) *h = DummyEncoding.height; 3716 3717 switch(id) { 3718 case PIXEL_FMT_YV12: 3719 case PIXEL_FMT_I420: 3720 *w = (*w + 7) & ~7; 3721 *h = (*h + 1) & ~1; 3722 pitchY = *w; 3723 pitchUV = *w >> 1; 3724 if(pitches) { 3725 pitches[0] = pitchY; 3726 pitches[1] = pitches[2] = pitchUV; 3727 } 3728 sizeY = pitchY * (*h); 3729 sizeUV = pitchUV * ((*h) >> 1); 3730 if(offsets) { 3731 offsets[0] = 0; 3732 offsets[1] = sizeY; 3733 offsets[2] = sizeY + sizeUV; 3734 } 3735 size = sizeY + (sizeUV << 1); 3736 break; 3737 case PIXEL_FMT_NV12: 3738 case PIXEL_FMT_NV21: 3739 *w = (*w + 7) & ~7; 3740 *h = (*h + 1) & ~1; 3741 pitchY = *w; 3742 pitchUV = *w; 3743 if(pitches) { 3744 pitches[0] = pitchY; 3745 pitches[1] = pitchUV; 3746 } 3747 sizeY = pitchY * (*h); 3748 sizeUV = pitchUV * ((*h) >> 1); 3749 if(offsets) { 3750 offsets[0] = 0; 3751 offsets[1] = sizeY; 3752 } 3753 size = sizeY + (sizeUV << 1); 3754 break; 3755 case PIXEL_FMT_YUY2: 3756 case PIXEL_FMT_UYVY: 3757 case PIXEL_FMT_YVYU: 3758 case PIXEL_FMT_RGB6: 3759 case PIXEL_FMT_RGB5: 3760 default: 3761 *w = (*w + 1) & ~1; 3762 pitchY = *w << 1; 3763 if(pitches) pitches[0] = pitchY; 3764 if(offsets) offsets[0] = 0; 3765 size = pitchY * (*h); 3766 break; 3767 } 3768 3769 return size; 3770} 3771 3772 3773/********************************* 3774 * OFFSCREEN SURFACES * 3775 *********************************/ 3776 3777static int 3778SISAllocSurface ( 3779 ScrnInfoPtr pScrn, 3780 int id, 3781 UShort w, 3782 UShort h, 3783 XF86SurfacePtr surface 3784) 3785{ 3786 SISPtr pSiS = SISPTR(pScrn); 3787 SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn); 3788 int size; 3789 3790 if((w < IMAGE_MIN_WIDTH) || (h < IMAGE_MIN_HEIGHT)) 3791 return BadValue; 3792 3793 if((w > DummyEncoding.width) || (h > DummyEncoding.height)) 3794 return BadValue; 3795 3796 if(pPriv->grabbedByV4L) 3797 return BadAlloc; 3798 3799 w = (w + 1) & ~1; 3800 pPriv->pitch = ((w << 1) + 63) & ~63; /* Only packed pixel modes supported */ 3801 size = h * pPriv->pitch; 3802 if(!(pPriv->offset = SISAllocateFBMemory(pScrn, &pPriv->handle, size))) 3803 return BadAlloc; 3804 3805 surface->width = w; 3806 surface->height = h; 3807 surface->pScrn = pScrn; 3808 surface->id = id; 3809 surface->pitches = &pPriv->pitch; 3810 surface->offsets = &pPriv->offset; 3811 surface->devPrivate.ptr = (pointer)pPriv; 3812 3813 close_overlay(pSiS, pPriv); 3814 pPriv->videoStatus = 0; 3815 REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 3816 pSiS->VideoTimerCallback = NULL; 3817 pPriv->grabbedByV4L = TRUE; 3818 return Success; 3819} 3820 3821static int 3822SISStopSurface (XF86SurfacePtr surface) 3823{ 3824 SISPortPrivPtr pPriv = (SISPortPrivPtr)(surface->devPrivate.ptr); 3825 SISPtr pSiS = SISPTR(surface->pScrn); 3826 3827 if(pPriv->grabbedByV4L && pPriv->videoStatus) { 3828 close_overlay(pSiS, pPriv); 3829 pPriv->mustwait = 1; 3830 pPriv->videoStatus = 0; 3831 } 3832 return Success; 3833} 3834 3835static int 3836SISFreeSurface (XF86SurfacePtr surface) 3837{ 3838 SISPortPrivPtr pPriv = (SISPortPrivPtr)(surface->devPrivate.ptr); 3839 3840 if(pPriv->grabbedByV4L) { 3841 SISStopSurface(surface); 3842 SISFreeFBMemory(surface->pScrn, &pPriv->handle); 3843 pPriv->grabbedByV4L = FALSE; 3844 } 3845 return Success; 3846} 3847 3848static int 3849SISGetSurfaceAttribute ( 3850 ScrnInfoPtr pScrn, 3851 Atom attribute, 3852 INT32 *value 3853) 3854{ 3855 SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn); 3856 3857 return SISGetPortAttribute(pScrn, attribute, value, (pointer)pPriv); 3858} 3859 3860static int 3861SISSetSurfaceAttribute( 3862 ScrnInfoPtr pScrn, 3863 Atom attribute, 3864 INT32 value 3865) 3866{ 3867 SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);; 3868 3869 return SISSetPortAttribute(pScrn, attribute, value, (pointer)pPriv); 3870} 3871 3872static int 3873SISDisplaySurface ( 3874 XF86SurfacePtr surface, 3875 short src_x, short src_y, 3876 short drw_x, short drw_y, 3877 short src_w, short src_h, 3878 short drw_w, short drw_h, 3879 RegionPtr clipBoxes 3880) 3881{ 3882 ScrnInfoPtr pScrn = surface->pScrn; 3883 SISPortPrivPtr pPriv = (SISPortPrivPtr)(surface->devPrivate.ptr); 3884#ifdef SIS_USE_XAA 3885 SISPtr pSiS = SISPTR(pScrn); 3886 int myreds[] = { 0x000000ff, 0x0000f800, 0, 0x00ff0000 }; 3887#endif 3888 3889 if(!pPriv->grabbedByV4L) return Success; 3890 3891 pPriv->drw_x = drw_x; 3892 pPriv->drw_y = drw_y; 3893 pPriv->drw_w = drw_w; 3894 pPriv->drw_h = drw_h; 3895 pPriv->src_x = src_x; 3896 pPriv->src_y = src_y; 3897 pPriv->src_w = src_w; 3898 pPriv->src_h = src_h; 3899 pPriv->id = surface->id; 3900 pPriv->height = surface->height; 3901 pPriv->bufAddr[0] = surface->offsets[0]; 3902 pPriv->currentBuf = 0; 3903 pPriv->srcPitch = surface->pitches[0]; 3904 3905 SISDisplayVideo(pScrn, pPriv); 3906 3907 if(pPriv->autopaintColorKey) { 3908#ifdef SIS_USE_XAA 3909 XAAInfoRecPtr pXAA = pSiS->AccelInfoPtr; 3910 3911 if((pPriv->NoOverlay) && pXAA && pXAA->FillMono8x8PatternRects) { 3912 (*pXAA->FillMono8x8PatternRects)(pScrn, 3913 myreds[(pSiS->CurrentLayout.bitsPerPixel >> 3) - 1], 3914 0x000000, GXcopy, ~0, 3915 REGION_NUM_RECTS(clipBoxes), 3916 REGION_RECTS(clipBoxes), 3917 0x00422418, 0x18244200, 0, 0); 3918 3919 } else { 3920#endif 3921#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,1,99,1,0) 3922 (*pXAA->FillSolidRects)(pScrn, pPriv->colorKey, GXcopy, ~0, 3923 REGION_NUM_RECTS(clipBoxes), 3924 REGION_RECTS(clipBoxes)); 3925#else 3926 xf86XVFillKeyHelper(pScrn->pScreen, (pPriv->NoOverlay) ? 0x00ff0000 : pPriv->colorKey, clipBoxes); 3927#endif 3928#ifdef SIS_USE_XAA 3929 } 3930#endif 3931 } 3932 3933 pPriv->videoStatus = CLIENT_VIDEO_ON; 3934 3935 return Success; 3936} 3937 3938#define NUMOFFSCRIMAGES_300 4 3939#define NUMOFFSCRIMAGES_315 5 3940 3941static XF86OffscreenImageRec SISOffscreenImages[NUMOFFSCRIMAGES_315] = 3942{ 3943 { 3944 &SISImages[0], /* YUV2 */ 3945 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, 3946 SISAllocSurface, 3947 SISFreeSurface, 3948 SISDisplaySurface, 3949 SISStopSurface, 3950 SISGetSurfaceAttribute, 3951 SISSetSurfaceAttribute, 3952 0, 0, /* Rest will be filled in */ 3953 0, 3954 NULL 3955 }, 3956 { 3957 &SISImages[2], /* UYVY */ 3958 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, 3959 SISAllocSurface, 3960 SISFreeSurface, 3961 SISDisplaySurface, 3962 SISStopSurface, 3963 SISGetSurfaceAttribute, 3964 SISSetSurfaceAttribute, 3965 0, 0, /* Rest will be filled in */ 3966 0, 3967 NULL 3968 } 3969 , 3970 { 3971 &SISImages[4], /* RV15 */ 3972 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, 3973 SISAllocSurface, 3974 SISFreeSurface, 3975 SISDisplaySurface, 3976 SISStopSurface, 3977 SISGetSurfaceAttribute, 3978 SISSetSurfaceAttribute, 3979 0, 0, /* Rest will be filled in */ 3980 0, 3981 NULL 3982 }, 3983 { 3984 &SISImages[5], /* RV16 */ 3985 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, 3986 SISAllocSurface, 3987 SISFreeSurface, 3988 SISDisplaySurface, 3989 SISStopSurface, 3990 SISGetSurfaceAttribute, 3991 SISSetSurfaceAttribute, 3992 0, 0, /* Rest will be filled in */ 3993 0, 3994 NULL 3995 }, 3996 { 3997 &SISImages[6], /* YVYU */ 3998 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, 3999 SISAllocSurface, 4000 SISFreeSurface, 4001 SISDisplaySurface, 4002 SISStopSurface, 4003 SISGetSurfaceAttribute, 4004 SISSetSurfaceAttribute, 4005 0, 0, /* Rest will be filled in */ 4006 0, 4007 NULL 4008 } 4009}; 4010 4011static void 4012SISInitOffscreenImages(ScreenPtr pScreen) 4013{ 4014 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 4015 SISPtr pSiS = SISPTR(pScrn); 4016 int i, num; 4017 4018 if(pSiS->VGAEngine == SIS_300_VGA) num = NUMOFFSCRIMAGES_300; 4019 else num = NUMOFFSCRIMAGES_315; 4020 4021 for(i = 0; i < num; i++) { 4022 SISOffscreenImages[i].max_width = DummyEncoding.width; 4023 SISOffscreenImages[i].max_height = DummyEncoding.height; 4024 if(pSiS->VGAEngine == SIS_300_VGA) { 4025 SISOffscreenImages[i].attributes = &SISAttributes_300[0]; 4026 SISOffscreenImages[i].num_attributes = SiSCountAttributes(&SISAttributes_300[0]); 4027 } else { 4028 SISOffscreenImages[i].attributes = &SISAttributes_315[0]; 4029 SISOffscreenImages[i].num_attributes = SiSCountAttributes(&SISAttributes_315[0]); 4030 if((pSiS->hasTwoOverlays) && (!(pSiS->SiS_SD2_Flags & SiS_SD2_SUPPORT760OO))) { 4031 SISOffscreenImages[i].num_attributes--; 4032 } 4033 } 4034 } 4035 xf86XVRegisterOffscreenImages(pScreen, SISOffscreenImages, num); 4036} 4037 4038/*****************************************************************/ 4039/* BLIT ADAPTORS */ 4040/*****************************************************************/ 4041#ifdef INCL_YUV_BLIT_ADAPTOR 4042 4043static void 4044SISSetPortDefaultsBlit(ScrnInfoPtr pScrn, SISBPortPrivPtr pPriv) 4045{ 4046 /* Default: Don't sync. */ 4047 pPriv->vsync = 0; 4048} 4049 4050static void 4051SISResetVideoBlit(ScrnInfoPtr pScrn) 4052{ 4053} 4054 4055static XF86VideoAdaptorPtr 4056SISSetupBlitVideo(ScreenPtr pScreen) 4057{ 4058 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 4059 SISPtr pSiS = SISPTR(pScrn); 4060 XF86VideoAdaptorPtr adapt; 4061 SISBPortPrivPtr pPriv; 4062 int i; 4063 4064#ifdef SIS_USE_XAA 4065 if(!pSiS->useEXA) { 4066 if(!pSiS->AccelInfoPtr) return NULL; 4067 } 4068#endif 4069 4070 if(!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + 4071 (sizeof(DevUnion) * NUM_BLIT_PORTS) + 4072 sizeof(SISBPortPrivRec)))) { 4073 return NULL; 4074 } 4075 4076 adapt->type = XvWindowMask | XvInputMask | XvImageMask; 4077 adapt->flags = 0; 4078 adapt->name = "SIS 315/330 series Video Blitter"; 4079 adapt->nEncodings = 1; 4080 adapt->pEncodings = &DummyEncodingBlit; 4081 adapt->nFormats = NUM_FORMATS; 4082 adapt->pFormats = SISFormats; 4083 adapt->nImages = NUM_IMAGES_BLIT; 4084 adapt->pImages = SISImagesBlit; 4085 adapt->pAttributes = SISAttributes_Blit; 4086 adapt->nAttributes = NUM_ATTRIBUTES_BLIT; 4087 adapt->nPorts = NUM_BLIT_PORTS; 4088 adapt->pPortPrivates = (DevUnion*)(&adapt[1]); 4089 4090 pSiS->blitPriv = (void *)(&adapt->pPortPrivates[NUM_BLIT_PORTS]); 4091 pPriv = (SISBPortPrivPtr)(pSiS->blitPriv); 4092 4093 for(i = 0; i < NUM_BLIT_PORTS; i++) { 4094 adapt->pPortPrivates[i].uval = (ULong)(i); 4095#if defined(REGION_NULL) 4096 REGION_NULL(pScreen, &pPriv->blitClip[i]); 4097#else 4098 REGION_INIT(pScreen, &pPriv->blitClip[i], NullBox, 0); 4099#endif 4100 pPriv->videoStatus[i] = 0; 4101 pPriv->currentBuf[i] = 0; 4102 pPriv->handle[i] = NULL; 4103 } 4104 4105 /* Scanline trigger not implemented by hardware! */ 4106 pPriv->VBlankTriggerCRT1 = 0; /* SCANLINE_TRIGGER_ENABLE | SCANLINE_TR_CRT1; */ 4107 pPriv->VBlankTriggerCRT2 = 0; /* SCANLINE_TRIGGER_ENABLE | SCANLINE_TR_CRT2; */ 4108 if(pSiS->ChipType >= SIS_330) { 4109 pPriv->AccelCmd = YUVRGB_BLIT_330; 4110 } else { 4111 pPriv->AccelCmd = YUVRGB_BLIT_325; 4112 } 4113 4114 adapt->PutVideo = NULL; 4115 adapt->PutStill = NULL; 4116 adapt->GetVideo = NULL; 4117 adapt->GetStill = NULL; 4118 adapt->StopVideo = (StopVideoFuncPtr)SISStopVideoBlit; 4119 adapt->SetPortAttribute = (SetPortAttributeFuncPtr)SISSetPortAttributeBlit; 4120 adapt->GetPortAttribute = (GetPortAttributeFuncPtr)SISGetPortAttributeBlit; 4121 adapt->QueryBestSize = (QueryBestSizeFuncPtr)SISQueryBestSizeBlit; 4122 adapt->PutImage = (PutImageFuncPtr)SISPutImageBlit; 4123 adapt->QueryImageAttributes = SISQueryImageAttributesBlit; 4124 4125 pSiS->blitadaptor = adapt; 4126 4127 pSiS->xvVSync = MAKE_ATOM(sisxvvsync); 4128 pSiS->xvSetDefaults = MAKE_ATOM(sisxvsetdefaults); 4129 4130 SISResetVideoBlit(pScrn); 4131 4132 /* Reset the properties to their defaults */ 4133 SISSetPortDefaultsBlit(pScrn, pPriv); 4134 4135 return adapt; 4136} 4137 4138static int 4139SISGetPortAttributeBlit(ScrnInfoPtr pScrn, Atom attribute, 4140 INT32 *value, ULong index) 4141{ 4142 SISPtr pSiS = SISPTR(pScrn); 4143 SISBPortPrivPtr pPriv = (SISBPortPrivPtr)(pSiS->blitPriv); 4144 4145 if(attribute == pSiS->xvVSync) { 4146 *value = pPriv->vsync; 4147 } else return BadMatch; 4148 return Success; 4149} 4150 4151static int 4152SISSetPortAttributeBlit(ScrnInfoPtr pScrn, Atom attribute, 4153 INT32 value, ULong index) 4154{ 4155 SISPtr pSiS = SISPTR(pScrn); 4156 SISBPortPrivPtr pPriv = (SISBPortPrivPtr)(pSiS->blitPriv); 4157 4158 if(attribute == pSiS->xvVSync) { 4159 if((value < 0) || (value > 1)) return BadValue; 4160 pPriv->vsync = value; 4161 } else if(attribute == pSiS->xvSetDefaults) { 4162 SISSetPortDefaultsBlit(pScrn, pPriv); 4163 } else return BadMatch; 4164 return Success; 4165} 4166 4167static void 4168SISStopVideoBlit(ScrnInfoPtr pScrn, ULong index, Bool shutdown) 4169{ 4170 SISPtr pSiS = SISPTR(pScrn); 4171 SISBPortPrivPtr pPriv = (SISBPortPrivPtr)(pSiS->blitPriv); 4172 4173 /* This shouldn't be called for blitter adaptors due to 4174 * adapt->flags but we provide it anyway. 4175 */ 4176 4177 if(index >= NUM_BLIT_PORTS) return; 4178 4179 REGION_EMPTY(pScrn->pScreen, &pPriv->blitClip[index]); 4180 4181 if(shutdown) { 4182 (*pSiS->SyncAccel)(pScrn); 4183 pPriv->videoStatus[index] = 0; 4184 SISFreeFBMemory(pScrn, &pPriv->handle[(int)index]); 4185 } 4186} 4187 4188static int 4189SISPutImageBlit( 4190 ScrnInfoPtr pScrn, 4191 short src_x, short src_y, 4192 short drw_x, short drw_y, 4193 short src_w, short src_h, 4194 short drw_w, short drw_h, 4195 int id, UChar *buf, 4196 short width, short height, 4197 Bool sync, 4198 RegionPtr clipBoxes, ULong index, 4199 DrawablePtr pDraw 4200){ 4201 SISPtr pSiS = SISPTR(pScrn); 4202 SISBPortPrivPtr pPriv = (SISBPortPrivPtr)(pSiS->blitPriv); 4203#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,1,99,1,0) 4204 XAAInfoRecPtr pXAA = pSiS->AccelInfoPtr; 4205#endif 4206 BoxPtr pbox = REGION_RECTS(clipBoxes); 4207 int nbox = REGION_NUM_RECTS(clipBoxes); 4208 CARD32 dstbase = 0, offsety, offsetuv, temp; 4209 int totalSize, bytesize=0, h, w, wb, srcPitch; 4210 int xoffset = 0, yoffset = 0, left, right, top, bottom; 4211 UChar *ybases, *ubases = NULL, *vbases = NULL, *myubases, *myvbases; 4212 UChar *ybased, *uvbased, packed; 4213 CARD16 *myuvbased; 4214 SiS_Packet12_YUV MyPacket; 4215#if 0 4216#ifdef SISMERGED 4217 Bool first; 4218#endif 4219#endif 4220 4221 if(index >= NUM_BLIT_PORTS) return BadMatch; 4222 4223 if(!height || !width) return Success; 4224 4225 switch(id) { 4226 case PIXEL_FMT_YV12: 4227 case PIXEL_FMT_I420: 4228 case PIXEL_FMT_NV12: 4229 case PIXEL_FMT_NV21: 4230 srcPitch = (width + 7) & ~7; /* Should come this way anyway */ 4231 bytesize = srcPitch * height; 4232 totalSize = (bytesize * 3) >> 1; 4233 break; 4234 case PIXEL_FMT_YUY2: 4235 case PIXEL_FMT_UYVY: 4236 case PIXEL_FMT_YVYU: 4237 srcPitch = ((width << 1) + 3) & ~3; 4238 /* Size = width * 2 * height */ 4239 totalSize = srcPitch * height; 4240 bytesize = 0; 4241 break; 4242 default: 4243 return BadMatch; 4244 } 4245 4246 /* allocate memory (we do doublebuffering) */ 4247 if(!(pPriv->bufAddr[index][0] = SISAllocateFBMemory(pScrn, &pPriv->handle[index], totalSize << 1))) 4248 return BadAlloc; 4249 4250 pPriv->bufAddr[index][1] = pPriv->bufAddr[index][0] + totalSize; 4251 4252 if(drw_w > width) { 4253 xoffset = (drw_w - width) >> 1; 4254 } 4255 if(drw_h > (height & ~1)) { 4256 yoffset = (drw_h - height) >> 1; 4257 } 4258 4259 if(xoffset || yoffset) { 4260#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,3,99,3,0) 4261 if(!RegionsEqual(&pPriv->blitClip[index], clipBoxes)) { 4262#else 4263 if(!REGION_EQUAL(pScrn->pScreen, &pPriv->blitClip[index], clipBoxes)) { 4264#endif 4265#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,1,99,1,0) 4266 (*pXAA->FillSolidRects)(pScrn, 0x00000000, GXcopy, ~0, 4267 REGION_NUM_RECTS(clipBoxes), 4268 REGION_RECTS(clipBoxes)); 4269#else 4270 xf86XVFillKeyHelper(pScrn->pScreen, 0x00000000, clipBoxes); 4271#endif 4272 REGION_COPY(pScrn->pScreen, &pPriv->blitClip[index], clipBoxes); 4273 } 4274 } 4275 4276 memset(&MyPacket, 0, sizeof(MyPacket)); 4277 4278 ybased = pSiS->FbBase + pPriv->bufAddr[index][pPriv->currentBuf[index]]; 4279 uvbased = pSiS->FbBase + pPriv->bufAddr[index][pPriv->currentBuf[index]] + bytesize; 4280 4281 ybases = buf; 4282 packed = 0; 4283 4284 switch(id) { 4285 case PIXEL_FMT_YV12: 4286 vbases = buf + bytesize; 4287 ubases = buf + bytesize*5/4; 4288 break; 4289 case PIXEL_FMT_I420: 4290 ubases = buf + bytesize; 4291 vbases = buf + bytesize*5/4; 4292 break; 4293 case PIXEL_FMT_NV12: 4294 MyPacket.P12_Command = YUV_FORMAT_NV12; 4295 break; 4296 case PIXEL_FMT_NV21: 4297 MyPacket.P12_Command = YUV_FORMAT_NV21; 4298 break; 4299 case PIXEL_FMT_YUY2: 4300 MyPacket.P12_Command = YUV_FORMAT_YUY2; 4301 packed = 1; 4302 break; 4303 case PIXEL_FMT_UYVY: 4304 MyPacket.P12_Command = YUV_FORMAT_UYVY; 4305 packed = 1; 4306 break; 4307 case PIXEL_FMT_YVYU: 4308 MyPacket.P12_Command = YUV_FORMAT_YVYU; 4309 packed = 1; 4310 break; 4311 default: 4312 return BadMatch; 4313 } 4314 4315 switch(id) { 4316 case PIXEL_FMT_YV12: 4317 case PIXEL_FMT_I420: 4318 MyPacket.P12_Command = YUV_FORMAT_NV12; 4319 /* Copy y plane */ 4320 SiSMemCopyToVideoRam(pSiS, ybased, ybases, bytesize); 4321 /* Copy u/v planes */ 4322 wb = srcPitch >> 1; 4323 h = height >> 1; 4324 while(h--) { 4325 myuvbased = (CARD16*)uvbased; 4326 myubases = ubases; 4327 myvbases = vbases; 4328 w = wb; 4329 while(w--) { 4330#if X_BYTE_ORDER == X_BIG_ENDIAN 4331 temp = (*myubases++) << 8; 4332 temp |= (*myvbases++); 4333#else 4334 temp = (*myvbases++) << 8; 4335 temp |= (*myubases++); 4336#endif 4337 *myuvbased++ = temp; 4338 } 4339 uvbased += srcPitch; 4340 ubases += wb; 4341 vbases += wb; 4342 } 4343 break; 4344 default: 4345 SiSMemCopyToVideoRam(pSiS, ybased, ybases, totalSize); 4346 } 4347 4348 dstbase += FBOFFSET; 4349 4350 MyPacket.P12_Header0 = SIS_PACKET12_HEADER0; 4351 MyPacket.P12_Header1 = SIS_PACKET12_HEADER1; 4352 MyPacket.P12_Null1 = SIS_NIL_CMD; 4353 MyPacket.P12_Null2 = SIS_NIL_CMD; 4354 MyPacket.P12_YPitch = MyPacket.P12_UVPitch = srcPitch; 4355 MyPacket.P12_DstAddr = dstbase; 4356 MyPacket.P12_DstPitch = pSiS->scrnOffset; 4357 MyPacket.P12_DstHeight = 0x0fff; 4358 4359 MyPacket.P12_Command |= pPriv->AccelCmd | 4360 SRCVIDEO | 4361 PATFG | 4362 pSiS->SiS310_AccelDepth | 4363 YUV_CMD_YUV | 4364 DSTVIDEO; 4365 4366 4367#if 0 /* Not implemented by hardware! */ 4368 if(pPriv->vsync) { 4369#ifdef SISMERGED 4370 if(!pSiS->MergedFB) { 4371#endif 4372#ifdef SISDUALHEAD 4373 if(pSiS->DualHeadMode) { 4374 if(pSiS->SecondHead) { 4375 MyPacket.P12_Command |= pPriv->VBlankTriggerCRT1; 4376 } else { 4377 MyPacket.P12_Command |= pPriv->VBlankTriggerCRT2; 4378 } 4379 } else { 4380#endif 4381 Bool IsSlaveMode = SiSBridgeIsInSlaveMode(pScrn); 4382 if((pSiS->VBFlags & DISPTYPE_DISP2) && !IsSlaveMode) 4383 MyPacket.P12_Command |= pPriv->VBlankTriggerCRT2; 4384 else if((pSiS->VBFlags & DISPTYPE_DISP1) || IsSlaveMode) 4385 MyPacket.P12_Command |= pPriv->VBlankTriggerCRT1; 4386#ifdef SISDUALHEAD 4387 } 4388#endif 4389#ifdef SISMERGED 4390 } 4391#endif 4392 } 4393#endif 4394 4395#if 0 4396#ifdef SISMERGED 4397 first = TRUE; 4398#endif 4399#endif 4400 while(nbox--) { 4401 left = pbox->x1; 4402 if(left >= drw_x + xoffset + width) goto mycont; 4403 4404 right = pbox->x2; 4405 if(right <= drw_x + xoffset) goto mycont; 4406 4407 top = pbox->y1; 4408 if(top >= drw_y + yoffset + height) goto mycont; 4409 4410 bottom = pbox->y2; 4411 if(bottom <= drw_y + yoffset) goto mycont; 4412 4413 if(left < (drw_x + xoffset)) left = drw_x + xoffset; 4414 if(right > (drw_x + xoffset + width)) right = drw_x + xoffset + width; 4415 if(top < (drw_y + yoffset)) top = drw_y + yoffset; 4416 if(bottom > (drw_y + yoffset + height)) bottom = drw_y + yoffset + height; 4417 4418 MyPacket.P12_DstX = left; 4419 MyPacket.P12_DstY = top; 4420 MyPacket.P12_RectWidth = right - left; 4421 MyPacket.P12_RectHeight = bottom - top; 4422 4423#if 0 4424#ifdef SISMERGED 4425 if((first) && (pSiS->MergedFB)) { 4426 int scrwidth = ((SiSMergedDisplayModePtr)pSiS->CurrentLayout.mode->Private)->CRT2->HDisplay; 4427 int scrheight = ((SiSMergedDisplayModePtr)pSiS->CurrentLayout.mode->Private)->CRT2->VDisplay; 4428 if( (right < pSiS->CRT2pScrn->frameX0) || 4429 (left >= pSiS->CRT2pScrn->frameX0 + scrwidth) || 4430 (bottom < pSiS->CRT2pScrn->frameY0) || 4431 (top >= pSiS->CRT2pScrn->frameY0 + scrheight) ) { 4432 MyPacket.P12_Command |= pPriv->VBlankTriggerCRT1; 4433 } else { 4434 MyPacket.P12_Command |= pPriv->VBlankTriggerCRT2; 4435 } 4436 } 4437#endif 4438#endif 4439 4440 offsety = offsetuv = 0; 4441 if(packed) { 4442 if(pbox->y1 > drw_y + yoffset) { 4443 offsetuv = (pbox->y1 - drw_y - yoffset) * srcPitch; 4444 } 4445 if(pbox->x1 > drw_x + xoffset) { 4446 offsetuv += ((pbox->x1 - drw_x - xoffset) << 1); 4447 if(offsetuv & 3) { 4448#if 0 /* Paint over covering object - no */ 4449 if(MyPacket.P12_DstX > 0) { 4450 offsetuv &= ~3; 4451 MyPacket.P12_DstX--; 4452 MyPacket.P12_RectWidth++; 4453 } else { 4454#endif 4455 offsetuv = (offsetuv + 3) & ~3; 4456 MyPacket.P12_DstX++; 4457 MyPacket.P12_RectWidth--; 4458#if 0 4459 } 4460#endif 4461 } 4462 } 4463 } else { 4464 if(pbox->y1 > drw_y + yoffset) { 4465 offsety = (pbox->y1 - drw_y - yoffset) * srcPitch; 4466 offsetuv = ((pbox->y1 - drw_y - yoffset) >> 1) * srcPitch; 4467 } 4468 if(pbox->x1 > drw_x + xoffset) { 4469 offsety += (pbox->x1 - drw_x - xoffset); 4470 offsetuv += (pbox->x1 - drw_x - xoffset); 4471 if(offsetuv & 1) { 4472 offsety++; 4473 offsetuv++; 4474 MyPacket.P12_DstX++; 4475 MyPacket.P12_RectWidth--; 4476 } 4477 } 4478 } 4479 4480 if(!MyPacket.P12_RectWidth) continue; 4481 4482 MyPacket.P12_YSrcAddr = pPriv->bufAddr[index][pPriv->currentBuf[index]] + offsety + FBOFFSET; 4483 MyPacket.P12_UVSrcAddr = pPriv->bufAddr[index][pPriv->currentBuf[index]] + bytesize + offsetuv + FBOFFSET; 4484 SISWriteBlitPacket(pSiS, (CARD32*)&MyPacket); 4485#if 0 4486 MyPacket.P12_Command &= ~(pPriv->VBlankTriggerCRT1 | pPriv->VBlankTriggerCRT2); 4487#endif 4488#if 0 4489#ifdef SISMERGED 4490 first = FALSE; 4491#endif 4492#endif 4493mycont: 4494 pbox++; 4495 } 4496 4497#if 0 4498 { 4499 int debug = 0; 4500 while( (SIS_MMIO_IN16(pSiS->IOBase, Q_STATUS+2) & 0x8000) != 0x8000) { debug++; }; 4501 while( (SIS_MMIO_IN16(pSiS->IOBase, Q_STATUS+2) & 0x8000) != 0x8000) { debug++; }; 4502 xf86DrvMsg(0, X_INFO, "vsync %d, debug %d\n", pPriv->vsync, debug); 4503 } 4504#endif 4505 4506 pPriv->currentBuf[index] ^= 1; 4507 4508 UpdateCurrentTime(); 4509 pPriv->freeTime[index] = currentTime.milliseconds + FREE_DELAY; 4510 pPriv->videoStatus[index] = FREE_TIMER; 4511 4512 pSiS->VideoTimerCallback = SISVideoTimerCallback; 4513 4514 return Success; 4515} 4516 4517static int 4518SISQueryImageAttributesBlit( 4519 ScrnInfoPtr pScrn, 4520 int id, 4521 UShort *w, UShort *h, 4522 int *pitches, int *offsets 4523){ 4524 int pitchY, pitchUV; 4525 int size, sizeY, sizeUV; 4526 4527 if(*w > DummyEncodingBlit.width) *w = DummyEncodingBlit.width; 4528 if(*h > DummyEncodingBlit.height) *h = DummyEncodingBlit.height; 4529 4530 switch(id) { 4531 case PIXEL_FMT_YV12: 4532 case PIXEL_FMT_I420: 4533 *w = (*w + 7) & ~7; 4534 *h = (*h + 1) & ~1; 4535 pitchY = *w; 4536 pitchUV = *w >> 1; 4537 if(pitches) { 4538 pitches[0] = pitchY; 4539 pitches[1] = pitches[2] = pitchUV; 4540 } 4541 sizeY = pitchY * (*h); 4542 sizeUV = pitchUV * ((*h) >> 1); 4543 if(offsets) { 4544 offsets[0] = 0; 4545 offsets[1] = sizeY; 4546 offsets[2] = sizeY + sizeUV; 4547 } 4548 size = sizeY + (sizeUV << 1); 4549 break; 4550 case PIXEL_FMT_NV12: 4551 case PIXEL_FMT_NV21: 4552 *w = (*w + 7) & ~7; 4553 pitchY = *w; 4554 pitchUV = *w; 4555 if(pitches) { 4556 pitches[0] = pitchY; 4557 pitches[1] = pitchUV; 4558 } 4559 sizeY = pitchY * (*h); 4560 sizeUV = pitchUV * ((*h) >> 1); 4561 if(offsets) { 4562 offsets[0] = 0; 4563 offsets[1] = sizeY; 4564 } 4565 size = sizeY + (sizeUV << 1); 4566 break; 4567 case PIXEL_FMT_YUY2: 4568 case PIXEL_FMT_UYVY: 4569 case PIXEL_FMT_YVYU: 4570 default: 4571 *w = (*w + 1) & ~1; 4572 pitchY = *w << 1; 4573 if(pitches) pitches[0] = pitchY; 4574 if(offsets) offsets[0] = 0; 4575 size = pitchY * (*h); 4576 break; 4577 } 4578 4579 return size; 4580} 4581 4582static void 4583SISQueryBestSizeBlit( 4584 ScrnInfoPtr pScrn, 4585 Bool motion, 4586 short vid_w, short vid_h, 4587 short drw_w, short drw_h, 4588 unsigned int *p_w, unsigned int *p_h, 4589 ULong index 4590){ 4591 /* We cannot scale */ 4592 *p_w = vid_w; 4593 *p_h = vid_h; 4594} 4595#endif /* INCL_YUV */ 4596 4597/*****************************************/ 4598/* TIMER CALLBACK */ 4599/*****************************************/ 4600 4601static void 4602SISVideoTimerCallback(ScrnInfoPtr pScrn, Time now) 4603{ 4604 SISPtr pSiS = SISPTR(pScrn); 4605 SISPortPrivPtr pPriv = NULL; 4606#ifdef INCL_YUV_BLIT_ADAPTOR 4607 SISBPortPrivPtr pPrivBlit = NULL; 4608#endif 4609 UChar sridx, cridx; 4610 Bool setcallback = FALSE; 4611 4612 if(!pScrn->vtSema) return; 4613 4614 if(pSiS->adaptor) { 4615 pPriv = GET_PORT_PRIVATE(pScrn); 4616 if(!pPriv->videoStatus) pPriv = NULL; 4617 } 4618 4619 if(pPriv) { 4620 if(pPriv->videoStatus & TIMER_MASK) { 4621 if(pPriv->videoStatus & OFF_TIMER) { 4622 setcallback = TRUE; 4623 if(pPriv->offTime < now) { 4624 /* Turn off the overlay */ 4625 sridx = inSISREG(SISSR); cridx = inSISREG(SISCR); 4626 close_overlay(pSiS, pPriv); 4627 outSISREG(SISSR, sridx); outSISREG(SISCR, cridx); 4628 pPriv->mustwait = 1; 4629 pPriv->videoStatus = FREE_TIMER; 4630 pPriv->freeTime = now + FREE_DELAY; 4631 } 4632 } else if(pPriv->videoStatus & FREE_TIMER) { 4633 if(pPriv->freeTime < now) { 4634 SISFreeFBMemory(pScrn, &pPriv->handle); 4635 pPriv->mustwait = 1; 4636 pPriv->videoStatus = 0; 4637 } else { 4638 setcallback = TRUE; 4639 } 4640 } 4641 } 4642 } 4643 4644#ifdef INCL_YUV_BLIT_ADAPTOR 4645 if(pSiS->blitadaptor) { 4646 int i; 4647 pPrivBlit = (SISBPortPrivPtr)(pSiS->blitPriv); 4648 for(i = 0; i < NUM_BLIT_PORTS; i++) { 4649 if(pPrivBlit->videoStatus[i] & FREE_TIMER) { 4650 if(pPrivBlit->freeTime[i] < now) { 4651 SISFreeFBMemory(pScrn, &pPrivBlit->handle[i]); 4652 pPrivBlit->videoStatus[i] = 0; 4653 } else { 4654 setcallback = TRUE; 4655 } 4656 } 4657 } 4658 } 4659#endif 4660 4661 pSiS->VideoTimerCallback = (setcallback) ? SISVideoTimerCallback : NULL; 4662} 4663 4664