172b676d7Smrg/* 272b676d7Smrg * Xv driver for SiS 300, 315 and 330 series. 372b676d7Smrg * 472b676d7Smrg * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria. 572b676d7Smrg * 672b676d7Smrg * Redistribution and use in source and binary forms, with or without 772b676d7Smrg * modification, are permitted provided that the following conditions 872b676d7Smrg * are met: 972b676d7Smrg * 1) Redistributions of source code must retain the above copyright 1072b676d7Smrg * notice, this list of conditions and the following disclaimer. 1172b676d7Smrg * 2) Redistributions in binary form must reproduce the above copyright 1272b676d7Smrg * notice, this list of conditions and the following disclaimer in the 1372b676d7Smrg * documentation and/or other materials provided with the distribution. 1472b676d7Smrg * 3) The name of the author may not be used to endorse or promote products 1572b676d7Smrg * derived from this software without specific prior written permission. 1672b676d7Smrg * 1772b676d7Smrg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1872b676d7Smrg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1972b676d7Smrg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2072b676d7Smrg * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2172b676d7Smrg * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2272b676d7Smrg * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2372b676d7Smrg * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2472b676d7Smrg * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2572b676d7Smrg * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2672b676d7Smrg * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2772b676d7Smrg * 2872b676d7Smrg * Author: Thomas Winischhofer <thomas@winischhofer.net> 2972b676d7Smrg * 3072b676d7Smrg * Formerly based on a mostly non-working code fragment for the 630 by 3172b676d7Smrg * Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan which is 3272b676d7Smrg * Copyright (C) 2000 Silicon Integrated Systems Corp, Inc. 3372b676d7Smrg * 3472b676d7Smrg * Basic structure based on the mga Xv driver by Mark Vojkovich 3572b676d7Smrg * and i810 Xv driver by Jonathan Bian <jonathan.bian@intel.com>. 3672b676d7Smrg * 3772b676d7Smrg * All comments in this file are by Thomas Winischhofer. 3872b676d7Smrg * 3972b676d7Smrg * The overlay adaptor supports the following chipsets: 4072b676d7Smrg * SiS300: No registers >0x65, two overlays (one used for CRT1, one for CRT2) 4172b676d7Smrg * SiS630/730: No registers >0x6b, two overlays (one used for CRT1, one for CRT2) 4272b676d7Smrg * SiS550: Full register range, two overlays (one used for CRT1, one for CRT2) 4372b676d7Smrg * SiS315: Full register range, one overlay (used for both CRT1 and CRT2 alt.) 4472b676d7Smrg * SiS650/740: Full register range, one overlay (used for both CRT1 and CRT2 alt.) 4572b676d7Smrg * SiSM650/651: Full register range, two overlays (one used for CRT1, one for CRT2) 4672b676d7Smrg * SiS330: Full register range, one overlay (used for both CRT1 and CRT2 alt.) 4772b676d7Smrg * SiS661/741/760: Full register range, two overlays (one used for CRT1, one for CRT2) 4872b676d7Smrg * SiS340: - ? overlays. Extended registers for DDA. 4972b676d7Smrg * SiS761: - ? overlays. Extended registers for DDA. 5072b676d7Smrg * XGI Volari V3XT/V5/V8: 1 Overlay. Extended registers for DDA. 5172b676d7Smrg * 5272b676d7Smrg * Help for reading the code: 5372b676d7Smrg * 315/550/650/740/M650/651/330/661/741/76x/340/XGI = SIS_315_VGA 5472b676d7Smrg * 300/630/730 = SIS_300_VGA 5572b676d7Smrg * For chipsets with 2 overlays, hasTwoOverlays will be true 5672b676d7Smrg * 5772b676d7Smrg * Notes on display modes: 5872b676d7Smrg * 5972b676d7Smrg * -) dual head mode: 6072b676d7Smrg * DISPMODE is either SINGLE1 or SINGLE2, hence you need to check dualHeadMode flag 6172b676d7Smrg * DISPMODE is _never_ MIRROR. 6272b676d7Smrg * a) Chipsets with 2 overlays: 6372b676d7Smrg * 315/330 series: Only half sized overlays available (width 960), 660: 1536 6472b676d7Smrg * Overlay 1 is used on CRT1, overlay 2 for CRT2. 6572b676d7Smrg * b) Chipsets with 1 overlay: 6672b676d7Smrg * Full size overlays available. 6772b676d7Smrg * Overlay is used for either CRT1 or CRT2 6872b676d7Smrg * -) merged fb mode: 6972b676d7Smrg * a) Chipsets with 2 overlays: 7072b676d7Smrg * 315/330 series: Only half sized overlays available (width 960), 660: 1536 7172b676d7Smrg * DISPMODE is always MIRROR. Overlay 1 is used for CRT1, overlay 2 for CRT2. 7272b676d7Smrg * b) Chipsets with 1 overlay: 7372b676d7Smrg * Full size overlays available. 7472b676d7Smrg * DISPMODE is either SINGLE1 or SINGLE2. Overlay is used accordingly on either 7572b676d7Smrg * CRT1 or CRT2 (automatically, where it is located) 7672b676d7Smrg * -) mirror mode (without dualhead or mergedfb) 7772b676d7Smrg * a) Chipsets with 2 overlays: 7872b676d7Smrg * 315/330 series: Only half sized overlays available (width 960), 660: 1536 7972b676d7Smrg * DISPMODE is MIRROR. Overlay 1 is used for CRT1, overlay 2 for CRT2. 8072b676d7Smrg * b) Chipsets with 1 overlay: 8172b676d7Smrg * Full size overlays available. 8272b676d7Smrg * DISPMODE is either SINGLE1 or SINGLE2. Overlay is used depending on 8372b676d7Smrg * XvOnCRT2 flag. 8472b676d7Smrg * 8572b676d7Smrg * About the video blitter: 8672b676d7Smrg * The video blitter adaptor supports 16 ports. By default, adaptor 0 will 8772b676d7Smrg * be the overlay adaptor, adaptor 1 the video blitter. The option XvDefaultAdaptor 8872b676d7Smrg * allows reversing this. 8972b676d7Smrg * Since SiS does not provide information on the 3D engine, I could not 9072b676d7Smrg * implement scaling. Instead, the driver paints a black border around the unscaled 9172b676d7Smrg * video if the destination area is bigger than the video. 9272b676d7Smrg * 9372b676d7Smrg */ 9472b676d7Smrg 9572b676d7Smrg#ifdef HAVE_CONFIG_H 9672b676d7Smrg#include "config.h" 9772b676d7Smrg#endif 9872b676d7Smrg 9972b676d7Smrg#include "sis.h" 10072b676d7Smrg#ifdef SIS_USE_XAA 10172b676d7Smrg#include "xf86fbman.h" 10272b676d7Smrg#endif 10372b676d7Smrg#include "regionstr.h" 10472b676d7Smrg 10572b676d7Smrg#include "xf86xv.h" 10672b676d7Smrg#include <X11/extensions/Xv.h> 10772b676d7Smrg#include "dixstruct.h" 10872b676d7Smrg#include "fourcc.h" 10972b676d7Smrg 11072b676d7Smrg#define SIS_NEED_inSISREG 11172b676d7Smrg#define SIS_NEED_outSISREG 11272b676d7Smrg#define SIS_NEED_inSISIDXREG 11372b676d7Smrg#define SIS_NEED_outSISIDXREG 11472b676d7Smrg#define SIS_NEED_setSISIDXREGmask 11572b676d7Smrg#define SIS_NEED_MYMMIO 11672b676d7Smrg#include "sis_regs.h" 11772b676d7Smrg 11872b676d7Smrg#ifdef INCL_YUV_BLIT_ADAPTOR 11972b676d7Smrg#include "sis310_accel.h" 12072b676d7Smrg#endif 12172b676d7Smrg 12272b676d7Smrg#include "sis_video.h" 12372b676d7Smrg 12472b676d7Smrg/********************************* 12572b676d7Smrg * Raw register access * 12672b676d7Smrg *********************************/ 12772b676d7Smrg 12872b676d7Smrg#if 0 12972b676d7Smrgstatic CARD32 _sisread(SISPtr pSiS, CARD32 reg) 13072b676d7Smrg{ 13172b676d7Smrg return *(pSiS->IOBase + reg); 13272b676d7Smrg} 13372b676d7Smrg 13472b676d7Smrgstatic void _siswrite(SISPtr pSiS, CARD32 reg, CARD32 data) 13572b676d7Smrg{ 13672b676d7Smrg *(pSiS->IOBase + reg) = data; 13772b676d7Smrg} 13872b676d7Smrg#endif 13972b676d7Smrg 14072b676d7Smrgstatic CARD8 getsrreg(SISPtr pSiS, CARD8 reg) 14172b676d7Smrg{ 14272b676d7Smrg CARD8 ret; 14372b676d7Smrg inSISIDXREG(SISSR, reg, ret); 14472b676d7Smrg return ret; 14572b676d7Smrg} 14672b676d7Smrg 14772b676d7Smrgstatic CARD8 getvideoreg(SISPtr pSiS, CARD8 reg) 14872b676d7Smrg{ 14972b676d7Smrg CARD8 ret; 15072b676d7Smrg inSISIDXREG(SISVID, reg, ret); 15172b676d7Smrg return ret; 15272b676d7Smrg} 15372b676d7Smrg 15472b676d7Smrgstatic __inline void setvideoreg(SISPtr pSiS, CARD8 reg, CARD8 data) 15572b676d7Smrg{ 15672b676d7Smrg outSISIDXREG(SISVID, reg, data); 15772b676d7Smrg} 15872b676d7Smrg 15972b676d7Smrgstatic __inline void setvideoregmask(SISPtr pSiS, CARD8 reg, CARD8 data, CARD8 mask) 16072b676d7Smrg{ 16172b676d7Smrg setSISIDXREGmask(SISVID, reg, data, mask); 16272b676d7Smrg} 16372b676d7Smrg 16472b676d7Smrgstatic void setsrregmask(SISPtr pSiS, CARD8 reg, CARD8 data, CARD8 mask) 16572b676d7Smrg{ 16672b676d7Smrg setSISIDXREGmask(SISSR, reg, data, mask); 16772b676d7Smrg} 16872b676d7Smrg 16972b676d7Smrg/* VBlank */ 17072b676d7Smrgstatic CARD8 vblank_active_CRT1(SISPtr pSiS, SISPortPrivPtr pPriv) 17172b676d7Smrg{ 17272b676d7Smrg return(inSISREG(SISINPSTAT) & 0x08); /* Verified */ 17372b676d7Smrg} 17472b676d7Smrg 17572b676d7Smrgstatic CARD8 vblank_active_CRT2(SISPtr pSiS, SISPortPrivPtr pPriv) 17672b676d7Smrg{ 17772b676d7Smrg CARD8 ret; 17872b676d7Smrg 17972b676d7Smrg if(pPriv->bridgeIsSlave) return(vblank_active_CRT1(pSiS, pPriv)); 18072b676d7Smrg 18172b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 18272b676d7Smrg inSISIDXREG(SISPART1, 0x30, ret); 18372b676d7Smrg } else { 18472b676d7Smrg inSISIDXREG(SISPART1, 0x25, ret); 18572b676d7Smrg } 18672b676d7Smrg return(ret & 0x02); /* Verified */ 18772b676d7Smrg} 18872b676d7Smrg 18972b676d7Smrg/* Scanline - unused */ 19072b676d7Smrg#if 0 19172b676d7Smrgstatic CARD16 get_scanline_CRT1(SISPtr pSiS) 19272b676d7Smrg{ 19372b676d7Smrg CARD32 line; 19472b676d7Smrg 19572b676d7Smrg _siswrite(pSiS, REG_PRIM_CRT_COUNTER, 0x00000001); 19672b676d7Smrg line = _sisread(pSiS, REG_PRIM_CRT_COUNTER); 19772b676d7Smrg 19872b676d7Smrg return((CARD16)((line >> 16) & 0x07FF)); 19972b676d7Smrg} 20072b676d7Smrg#endif 20172b676d7Smrg 20272b676d7Smrgstatic CARD16 get_scanline_CRT2(SISPtr pSiS, SISPortPrivPtr pPriv) 20372b676d7Smrg{ 20472b676d7Smrg CARD8 reg1, reg2; 20572b676d7Smrg 20672b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 20772b676d7Smrg inSISIDXREG(SISPART1, 0x32, reg1); 20872b676d7Smrg inSISIDXREG(SISPART1, 0x33, reg2); 20972b676d7Smrg } else { 21072b676d7Smrg inSISIDXREG(SISPART1, 0x27, reg1); 21172b676d7Smrg inSISIDXREG(SISPART1, 0x28, reg2); 21272b676d7Smrg } 21372b676d7Smrg 21472b676d7Smrg return((CARD16)(reg1 | ((reg2 & 0x70) << 4))); 21572b676d7Smrg} 21672b676d7Smrg 21772b676d7Smrg/* Helper: Count attributes */ 21872b676d7Smrgstatic int 21972b676d7SmrgSiSCountAttributes(XF86AttributeRec *attrs) 22072b676d7Smrg{ 22172b676d7Smrg int num = 0; 22272b676d7Smrg 22372b676d7Smrg while(attrs[num].name) num++; 22472b676d7Smrg 22572b676d7Smrg return num; 22672b676d7Smrg} 22772b676d7Smrg 22872b676d7Smrg/********************************* 22972b676d7Smrg * Video gamma * 23072b676d7Smrg *********************************/ 23172b676d7Smrg 23272b676d7Smrgstatic void 23372b676d7SmrgSiSComputeXvGamma(SISPtr pSiS) 23472b676d7Smrg{ 23572b676d7Smrg int num = 255, i; 23672b676d7Smrg double red = 1.0 / (double)((double)pSiS->XvGammaRed / 1000); 23772b676d7Smrg double green = 1.0 / (double)((double)pSiS->XvGammaGreen / 1000); 23872b676d7Smrg double blue = 1.0 / (double)((double)pSiS->XvGammaBlue / 1000); 23972b676d7Smrg 24072b676d7Smrg for(i = 0; i <= num; i++) { 24172b676d7Smrg pSiS->XvGammaRampRed[i] = 24272b676d7Smrg (red == 1.0) ? i : (CARD8)(pow((double)i / (double)num, red) * (double)num + 0.5); 24372b676d7Smrg 24472b676d7Smrg pSiS->XvGammaRampGreen[i] = 24572b676d7Smrg (green == 1.0) ? i : (CARD8)(pow((double)i / (double)num, green) * (double)num + 0.5); 24672b676d7Smrg 24772b676d7Smrg pSiS->XvGammaRampBlue[i] = 24872b676d7Smrg (blue == 1.0) ? i : (CARD8)(pow((double)i / (double)num, blue) * (double)num + 0.5); 24972b676d7Smrg } 25072b676d7Smrg} 25172b676d7Smrg 25272b676d7Smrgstatic void 25372b676d7SmrgSiSSetXvGamma(SISPtr pSiS) 25472b676d7Smrg{ 25572b676d7Smrg int i; 25672b676d7Smrg UChar backup = getsrreg(pSiS, 0x1f); 25772b676d7Smrg setsrregmask(pSiS, 0x1f, 0x08, 0x18); 25872b676d7Smrg for(i = 0; i <= 255; i++) { 25972b676d7Smrg SIS_MMIO_OUT32(pSiS->IOBase, 0x8570, 26072b676d7Smrg (i << 24) | 26172b676d7Smrg (pSiS->XvGammaRampBlue[i] << 16) | 26272b676d7Smrg (pSiS->XvGammaRampGreen[i] << 8) | 26372b676d7Smrg pSiS->XvGammaRampRed[i]); 26472b676d7Smrg } 26572b676d7Smrg setsrregmask(pSiS, 0x1f, backup, 0xff); 26672b676d7Smrg} 26772b676d7Smrg 26872b676d7Smrgvoid 26972b676d7SmrgSiSUpdateXvGamma(SISPtr pSiS, SISPortPrivPtr pPriv) 27072b676d7Smrg{ 27172b676d7Smrg UChar sr7 = getsrreg(pSiS, 0x07); 27272b676d7Smrg 27372b676d7Smrg if(!pSiS->XvGamma) return; 27472b676d7Smrg if(!(pSiS->MiscFlags & MISC_CRT1OVERLAYGAMMA)) return; 27572b676d7Smrg 27672b676d7Smrg#ifdef SISDUALHEAD 27772b676d7Smrg if((pPriv->dualHeadMode) && (!pSiS->SecondHead)) return; 27872b676d7Smrg#endif 27972b676d7Smrg 28072b676d7Smrg if(!(sr7 & 0x04)) return; 28172b676d7Smrg 28272b676d7Smrg SiSComputeXvGamma(pSiS); 28372b676d7Smrg SiSSetXvGamma(pSiS); 28472b676d7Smrg} 28572b676d7Smrg 28672b676d7Smrgstatic void 28772b676d7SmrgSISResetXvGamma(ScrnInfoPtr pScrn) 28872b676d7Smrg{ 28972b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 29072b676d7Smrg SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn); 29172b676d7Smrg 29272b676d7Smrg SiSUpdateXvGamma(pSiS, pPriv); 29372b676d7Smrg} 29472b676d7Smrg 29572b676d7Smrg/********************************* 29672b676d7Smrg * InitVideo() * 29772b676d7Smrg *********************************/ 29872b676d7Smrg 29972b676d7Smrgvoid 30072b676d7SmrgSISInitVideo(ScreenPtr pScreen) 30172b676d7Smrg{ 30274c14cd6Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 30372b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 30472b676d7Smrg XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; 30572b676d7Smrg XF86VideoAdaptorPtr newAdaptor = NULL, newBlitAdaptor = NULL; 30672b676d7Smrg int num_adaptors; 30772b676d7Smrg 30872b676d7Smrg newAdaptor = SISSetupImageVideo(pScreen); 30972b676d7Smrg if(newAdaptor) { 31072b676d7Smrg SISInitOffscreenImages(pScreen); 31172b676d7Smrg } 31272b676d7Smrg 31372b676d7Smrg#ifdef INCL_YUV_BLIT_ADAPTOR 31472b676d7Smrg if( ( (pSiS->ChipFlags & SiSCF_Is65x) || 31572b676d7Smrg (pSiS->ChipType >= SIS_330) ) && 31672b676d7Smrg (pScrn->bitsPerPixel != 8) ) { 31772b676d7Smrg newBlitAdaptor = SISSetupBlitVideo(pScreen); 31872b676d7Smrg } 31972b676d7Smrg#endif 32072b676d7Smrg 32172b676d7Smrg num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); 32272b676d7Smrg 32372b676d7Smrg if(newAdaptor || newBlitAdaptor) { 32472b676d7Smrg int size = num_adaptors; 32572b676d7Smrg 32672b676d7Smrg if(newAdaptor) size++; 32772b676d7Smrg if(newBlitAdaptor) size++; 32872b676d7Smrg 32974c14cd6Smrg newAdaptors = malloc(size * sizeof(XF86VideoAdaptorPtr*)); 33072b676d7Smrg if(newAdaptors) { 33172b676d7Smrg if(num_adaptors) { 33272b676d7Smrg memcpy(newAdaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr)); 33372b676d7Smrg } 33472b676d7Smrg if(pSiS->XvDefAdaptorBlit) { 33572b676d7Smrg if(newBlitAdaptor) { 33672b676d7Smrg newAdaptors[num_adaptors] = newBlitAdaptor; 33772b676d7Smrg num_adaptors++; 33872b676d7Smrg } 33972b676d7Smrg } 34072b676d7Smrg if(newAdaptor) { 34172b676d7Smrg newAdaptors[num_adaptors] = newAdaptor; 34272b676d7Smrg num_adaptors++; 34372b676d7Smrg } 34472b676d7Smrg if(!pSiS->XvDefAdaptorBlit) { 34572b676d7Smrg if(newBlitAdaptor) { 34672b676d7Smrg newAdaptors[num_adaptors] = newBlitAdaptor; 34772b676d7Smrg num_adaptors++; 34872b676d7Smrg } 34972b676d7Smrg } 35072b676d7Smrg adaptors = newAdaptors; 35172b676d7Smrg } 35272b676d7Smrg } 35372b676d7Smrg 35472b676d7Smrg if(num_adaptors) { 35572b676d7Smrg xf86XVScreenInit(pScreen, adaptors, num_adaptors); 35672b676d7Smrg } 35772b676d7Smrg 35872b676d7Smrg if(newAdaptors) { 35974c14cd6Smrg free(newAdaptors); 36072b676d7Smrg } 36172b676d7Smrg} 36272b676d7Smrg 36372b676d7Smrg/********************************* 36472b676d7Smrg * SetPortsDefault() * 36572b676d7Smrg *********************************/ 36672b676d7Smrg 36772b676d7Smrgvoid 36872b676d7SmrgSISSetPortDefaults(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) 36972b676d7Smrg{ 37072b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 37172b676d7Smrg#ifdef SISDUALHEAD 37272b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate;; 37372b676d7Smrg#endif 37472b676d7Smrg 37572b676d7Smrg pPriv->colorKey = pSiS->colorKey = 0x000101fe; 37672b676d7Smrg pPriv->brightness = pSiS->XvDefBri; 37772b676d7Smrg pPriv->contrast = pSiS->XvDefCon; 37872b676d7Smrg pPriv->hue = pSiS->XvDefHue; 37972b676d7Smrg pPriv->saturation = pSiS->XvDefSat; 38072b676d7Smrg pPriv->autopaintColorKey = TRUE; 38172b676d7Smrg pPriv->disablegfx = pSiS->XvDefDisableGfx; 38272b676d7Smrg pPriv->disablegfxlr= pSiS->XvDefDisableGfxLR; 38372b676d7Smrg pSiS->disablecolorkeycurrent = pSiS->XvDisableColorKey; 38472b676d7Smrg pPriv->usechromakey = pSiS->XvUseChromaKey; 38572b676d7Smrg pPriv->insidechromakey = pSiS->XvInsideChromaKey; 38672b676d7Smrg pPriv->yuvchromakey = pSiS->XvYUVChromaKey; 38772b676d7Smrg pPriv->chromamin = pSiS->XvChromaMin; 38872b676d7Smrg pPriv->chromamax = pSiS->XvChromaMax; 38972b676d7Smrg if(pPriv->dualHeadMode) { 39072b676d7Smrg#ifdef SISDUALHEAD 39172b676d7Smrg if(!pSiS->SecondHead) { 39272b676d7Smrg pPriv->tvxpos = pSiS->tvxpos; 39372b676d7Smrg pPriv->tvypos = pSiS->tvypos; 39472b676d7Smrg pPriv->updatetvxpos = TRUE; 39572b676d7Smrg pPriv->updatetvypos = TRUE; 39672b676d7Smrg } 39772b676d7Smrg#endif 39872b676d7Smrg } else { 39972b676d7Smrg pPriv->tvxpos = pSiS->tvxpos; 40072b676d7Smrg pPriv->tvypos = pSiS->tvypos; 40172b676d7Smrg pPriv->updatetvxpos = TRUE; 40272b676d7Smrg pPriv->updatetvypos = TRUE; 40372b676d7Smrg } 40472b676d7Smrg#ifdef SIS_CP 40572b676d7Smrg SIS_CP_VIDEO_DEF 40672b676d7Smrg#endif 40772b676d7Smrg if(pPriv->dualHeadMode) { 40872b676d7Smrg#ifdef SISDUALHEAD 40972b676d7Smrg pPriv->crtnum = 41072b676d7Smrg pSiSEnt->curxvcrtnum = 41172b676d7Smrg pSiSEnt->XvOnCRT2 ? 1 : 0; 41272b676d7Smrg#endif 41372b676d7Smrg } else 41472b676d7Smrg pPriv->crtnum = pSiS->XvOnCRT2 ? 1 : 0; 41572b676d7Smrg 41672b676d7Smrg pSiS->XvGammaRed = pSiS->XvGammaRedDef; 41772b676d7Smrg pSiS->XvGammaGreen = pSiS->XvGammaGreenDef; 41872b676d7Smrg pSiS->XvGammaBlue = pSiS->XvGammaBlueDef; 41972b676d7Smrg SiSUpdateXvGamma(pSiS, pPriv); 42072b676d7Smrg} 42172b676d7Smrg 42272b676d7Smrg/********************************* 42372b676d7Smrg * ResetVideo() * 42472b676d7Smrg *********************************/ 42572b676d7Smrg 42672b676d7Smrgstatic void 42772b676d7SmrgSISResetVideo(ScrnInfoPtr pScrn) 42872b676d7Smrg{ 42972b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 43072b676d7Smrg SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn); 43172b676d7Smrg 43272b676d7Smrg /* Unlock registers */ 43372b676d7Smrg#ifdef UNLOCK_ALWAYS 43472b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 43572b676d7Smrg#endif 43672b676d7Smrg if(getvideoreg (pSiS, Index_VI_Passwd) != 0xa1) { 43772b676d7Smrg setvideoreg (pSiS, Index_VI_Passwd, 0x86); 43872b676d7Smrg if(getvideoreg (pSiS, Index_VI_Passwd) != 0xa1) 43972b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 44072b676d7Smrg "Xv: Video password could not unlock registers\n"); 44172b676d7Smrg } 44272b676d7Smrg 44372b676d7Smrg /* Initialize first overlay (CRT1) ------------------------------- */ 44472b676d7Smrg 44572b676d7Smrg /* This bit has obviously a different meaning on 315 series (linebuffer-related) */ 44672b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA) { 44772b676d7Smrg /* Write-enable video registers */ 44872b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x80, 0x81); 44972b676d7Smrg } else { 45072b676d7Smrg /* Select overlay 2, clear all linebuffer related bits */ 45172b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0xb1); 45272b676d7Smrg } 45372b676d7Smrg 45472b676d7Smrg /* Disable overlay */ 45572b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02); 45672b676d7Smrg 45772b676d7Smrg /* Disable bob de-interlacer and some strange bit */ 45872b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x82); 45972b676d7Smrg 46072b676d7Smrg /* Select RGB chroma key format (300 series only) */ 46172b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA) { 46272b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x40); 46372b676d7Smrg } 46472b676d7Smrg 46572b676d7Smrg /* Reset scale control and contrast */ 46672b676d7Smrg /* (Enable DDA (interpolation)) */ 46772b676d7Smrg setvideoregmask(pSiS, Index_VI_Scale_Control, 0x60, 0x60); 46872b676d7Smrg setvideoregmask(pSiS, Index_VI_Contrast_Enh_Ctrl, 0x04, 0x1F); 46972b676d7Smrg 47072b676d7Smrg setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Preset_Low, 0x00); 47172b676d7Smrg setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Preset_Middle, 0x00); 47272b676d7Smrg setvideoreg(pSiS, Index_VI_UV_Buf_Preset_Low, 0x00); 47372b676d7Smrg setvideoreg(pSiS, Index_VI_UV_Buf_Preset_Middle, 0x00); 47472b676d7Smrg setvideoreg(pSiS, Index_VI_Disp_Y_UV_Buf_Preset_High, 0x00); 47572b676d7Smrg setvideoreg(pSiS, Index_VI_Play_Threshold_Low, 0x00); 47672b676d7Smrg setvideoreg(pSiS, Index_VI_Play_Threshold_High, 0x00); 47772b676d7Smrg if(pSiS->Chipset == PCI_CHIP_SIS330) { 47872b676d7Smrg /* Disable contrast enhancement (?) */ 47972b676d7Smrg setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x00, 0x10); 48072b676d7Smrg } else if(pPriv->is661741760) { 48172b676d7Smrg setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x00, 0xE0); 48272b676d7Smrg if(pPriv->is760) { 48372b676d7Smrg setvideoregmask(pSiS, Index_VI_V_Buf_Start_Over, 0x3c, 0x3c); 48472b676d7Smrg } else { /* 661, 741 */ 48572b676d7Smrg setvideoregmask(pSiS, Index_VI_V_Buf_Start_Over, 0x2c, 0x3c); 48672b676d7Smrg } 48772b676d7Smrg } else if((pSiS->Chipset == PCI_CHIP_SIS340) || 48872b676d7Smrg (pSiS->Chipset == PCI_CHIP_XGIXG20) || 48972b676d7Smrg (pSiS->Chipset == PCI_CHIP_XGIXG40)) { 49072b676d7Smrg /* Disable contrast enhancement (?) */ 49172b676d7Smrg setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x00, 0x10); 49272b676d7Smrg /* Threshold high */ 49372b676d7Smrg setvideoregmask(pSiS, 0xb5, 0x00, 0x01); 49472b676d7Smrg setvideoregmask(pSiS, 0xb6, 0x00, 0x01); 49572b676d7Smrg /* Enable horizontal, disable vertical 4-tap DDA scaler */ 49672b676d7Smrg setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x40, 0xc0); 49772b676d7Smrg set_dda_regs(pSiS, 1.0); 49872b676d7Smrg /* Enable software-flip */ 49972b676d7Smrg setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x20, 0x20); 50072b676d7Smrg /* "Disable video processor" */ 50172b676d7Smrg setsrregmask(pSiS, 0x3f, 0x00, 0x02); 50272b676d7Smrg } else if(pPriv->is761) { 50372b676d7Smrg /* Disable contrast enhancement (?) */ 50472b676d7Smrg setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x00, 0x10); 50572b676d7Smrg /* Threshold high */ 50672b676d7Smrg setvideoregmask(pSiS, 0xb5, 0x00, 0x01); 50772b676d7Smrg setvideoregmask(pSiS, 0xb6, 0x00, 0x01); 50872b676d7Smrg /* Enable horizontal, disable vertical 4-tap DDA scaler */ 50972b676d7Smrg setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x40, 0xC0); 51072b676d7Smrg /* ? */ 51172b676d7Smrg setvideoregmask(pSiS, 0xb6, 0x02, 0x02); 51272b676d7Smrg set_dda_regs(pSiS, 1.0); 51372b676d7Smrg setvideoregmask(pSiS, Index_VI_V_Buf_Start_Over, 0x00, 0x3c); 51472b676d7Smrg } 51572b676d7Smrg 51672b676d7Smrg if((pSiS->ChipFlags & SiSCF_Is65x) || (pPriv->is661741760)) { 51772b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0x04); 51872b676d7Smrg } 51972b676d7Smrg 52072b676d7Smrg /* Reset top window position for scanline check */ 52172b676d7Smrg setvideoreg(pSiS, Index_VI_Win_Ver_Disp_Start_Low, 0x00); 52272b676d7Smrg setvideoreg(pSiS, Index_VI_Win_Ver_Over, 0x00); 52372b676d7Smrg 52472b676d7Smrg /* Initialize second overlay (CRT2) - only for 300, 630/730, 550, M650/651, 661/741/660/760 */ 52572b676d7Smrg if(pSiS->hasTwoOverlays) { 52672b676d7Smrg 52772b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA) { 52872b676d7Smrg /* Write-enable video registers */ 52972b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x81, 0x81); 53072b676d7Smrg } else { 53172b676d7Smrg /* Select overlay 2, clear all linebuffer related bits */ 53272b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, 0xb1); 53372b676d7Smrg } 53472b676d7Smrg 53572b676d7Smrg /* Disable overlay */ 53672b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02); 53772b676d7Smrg 53872b676d7Smrg /* Disable bob de-interlacer and some strange bit */ 53972b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x82); 54072b676d7Smrg 54172b676d7Smrg /* Select RGB chroma key format */ 54272b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA) { 54372b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x40); 54472b676d7Smrg } 54572b676d7Smrg 54672b676d7Smrg /* Reset scale control and contrast */ 54772b676d7Smrg /* (Enable DDA (interpolation)) */ 54872b676d7Smrg setvideoregmask(pSiS, Index_VI_Scale_Control, 0x60, 0x60); 54972b676d7Smrg setvideoregmask(pSiS, Index_VI_Contrast_Enh_Ctrl, 0x04, 0x1F); 55072b676d7Smrg 55172b676d7Smrg setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Preset_Low, 0x00); 55272b676d7Smrg setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Preset_Middle, 0x00); 55372b676d7Smrg setvideoreg(pSiS, Index_VI_UV_Buf_Preset_Low, 0x00); 55472b676d7Smrg setvideoreg(pSiS, Index_VI_UV_Buf_Preset_Middle, 0x00); 55572b676d7Smrg setvideoreg(pSiS, Index_VI_Disp_Y_UV_Buf_Preset_High, 0x00); 55672b676d7Smrg setvideoreg(pSiS, Index_VI_Play_Threshold_Low, 0x00); 55772b676d7Smrg setvideoreg(pSiS, Index_VI_Play_Threshold_High, 0x00); 55872b676d7Smrg 55972b676d7Smrg if(pPriv->is661741760) { 56072b676d7Smrg CARD8 temp; 56172b676d7Smrg setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x00, 0xE0); 56272b676d7Smrg switch(pSiS->ChipType) { 56372b676d7Smrg case SIS_661: temp = 0x24; break; 56472b676d7Smrg case SIS_741: temp = 0x2c; break; 56572b676d7Smrg default: temp = 0x3c; 56672b676d7Smrg } 56772b676d7Smrg setvideoregmask(pSiS, Index_VI_V_Buf_Start_Over, temp, 0x3c); 56872b676d7Smrg } else if(pPriv->is761) { 56972b676d7Smrg setvideoregmask(pSiS, Index_VI_V_Buf_Start_Over, 0x00, 0x3c); 57072b676d7Smrg } else if(pSiS->Chipset == PCI_CHIP_SIS340) { /* 2 overlays? */ 57172b676d7Smrg setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x00, 0x10); 57272b676d7Smrg setvideoregmask(pSiS, 0xb5, 0x00, 0x01); 57372b676d7Smrg setvideoregmask(pSiS, 0xb6, 0x00, 0x01); 57472b676d7Smrg setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x40, 0xC0); 57572b676d7Smrg set_dda_regs(pSiS, 1.0); 57672b676d7Smrg setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x20, 0x20); 57772b676d7Smrg } 57872b676d7Smrg 57972b676d7Smrg setvideoreg(pSiS, Index_VI_Win_Ver_Disp_Start_Low, 0x00); 58072b676d7Smrg setvideoreg(pSiS, Index_VI_Win_Ver_Over, 0x00); 58172b676d7Smrg 58272b676d7Smrg } 58372b676d7Smrg 58472b676d7Smrg /* set default properties for overlay 1 (CRT1) -------------------------- */ 58572b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0x01); 58672b676d7Smrg setvideoregmask(pSiS, Index_VI_Contrast_Enh_Ctrl, 0x04, 0x07); 58772b676d7Smrg setvideoreg(pSiS, Index_VI_Brightness, 0x20); 58872b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 58972b676d7Smrg setvideoreg(pSiS, Index_VI_Hue, 0x00); 59072b676d7Smrg setvideoreg(pSiS, Index_VI_Saturation, 0x00); 59172b676d7Smrg } 59272b676d7Smrg 59372b676d7Smrg /* set default properties for overlay 2(CRT2) -------------------------- */ 59472b676d7Smrg if(pSiS->hasTwoOverlays) { 59572b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, 0x01); 59672b676d7Smrg setvideoregmask(pSiS, Index_VI_Contrast_Enh_Ctrl, 0x04, 0x07); 59772b676d7Smrg setvideoreg(pSiS, Index_VI_Brightness, 0x20); 59872b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 59972b676d7Smrg setvideoreg(pSiS, Index_VI_Hue, 0x00); 60072b676d7Smrg setvideoreg(pSiS, Index_VI_Saturation, 0x00); 60172b676d7Smrg } 60272b676d7Smrg } 60372b676d7Smrg 60472b676d7Smrg /* Reset Xv gamma correction */ 60572b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 60672b676d7Smrg SiSUpdateXvGamma(pSiS, pPriv); 60772b676d7Smrg } 60872b676d7Smrg 60972b676d7Smrg pPriv->mustresettap = TRUE; 61072b676d7Smrg#ifdef SISMERGED 61172b676d7Smrg pPriv->mustresettap2 = TRUE; 61272b676d7Smrg#endif 61372b676d7Smrg} 61472b676d7Smrg 61572b676d7Smrg/********************************* 61672b676d7Smrg * Set displaymode * 61772b676d7Smrg *********************************/ 61872b676d7Smrg 61972b676d7Smrg/* Set display mode (single CRT1/CRT2, mirror). 62072b676d7Smrg * MIRROR mode is only available on chipsets with two overlays. 62172b676d7Smrg * On the other chipsets, if only CRT1 or only CRT2 are used, 62272b676d7Smrg * the correct display CRT is chosen automatically. If both 62372b676d7Smrg * CRT1 and CRT2 are connected, the user can choose between CRT1 and 62472b676d7Smrg * CRT2 by using the option XvOnCRT2. 62572b676d7Smrg */ 62672b676d7Smrg 62772b676d7Smrgstatic void 62872b676d7Smrgset_dispmode(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) 62972b676d7Smrg{ 63072b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 63172b676d7Smrg 63272b676d7Smrg pPriv->dualHeadMode = pPriv->bridgeIsSlave = FALSE; 63372b676d7Smrg 63472b676d7Smrg if(SiSBridgeIsInSlaveMode(pScrn)) { 63572b676d7Smrg pPriv->bridgeIsSlave = TRUE; 63672b676d7Smrg } 63772b676d7Smrg 63872b676d7Smrg if( (pSiS->VBFlags & VB_DISPMODE_MIRROR) || 63972b676d7Smrg ((pPriv->bridgeIsSlave) && (pSiS->VBFlags & DISPTYPE_DISP2)) ) { 64072b676d7Smrg if(pPriv->hasTwoOverlays) 64172b676d7Smrg pPriv->displayMode = DISPMODE_MIRROR; /* CRT1+CRT2 (2 overlays) */ 64272b676d7Smrg else if(pPriv->crtnum) 64372b676d7Smrg pPriv->displayMode = DISPMODE_SINGLE2; /* CRT2 only */ 64472b676d7Smrg else 64572b676d7Smrg pPriv->displayMode = DISPMODE_SINGLE1; /* CRT1 only */ 64672b676d7Smrg } else { 64772b676d7Smrg#ifdef SISDUALHEAD 64872b676d7Smrg if(pSiS->DualHeadMode) { 64972b676d7Smrg pPriv->dualHeadMode = TRUE; 65072b676d7Smrg if(pSiS->SecondHead) 65172b676d7Smrg pPriv->displayMode = DISPMODE_SINGLE1; /* CRT1 only */ 65272b676d7Smrg else 65372b676d7Smrg pPriv->displayMode = DISPMODE_SINGLE2; /* CRT2 only */ 65472b676d7Smrg } else 65572b676d7Smrg#endif 65672b676d7Smrg if(pSiS->VBFlags & DISPTYPE_DISP1) { 65772b676d7Smrg pPriv->displayMode = DISPMODE_SINGLE1; /* CRT1 only */ 65872b676d7Smrg } else { 65972b676d7Smrg pPriv->displayMode = DISPMODE_SINGLE2; /* CRT2 only */ 66072b676d7Smrg } 66172b676d7Smrg } 66272b676d7Smrg} 66372b676d7Smrg 66472b676d7Smrgstatic void 66572b676d7Smrgset_disptype_regs(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) 66672b676d7Smrg{ 66772b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 66872b676d7Smrg#ifdef SISDUALHEAD 66972b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 67072b676d7Smrg int crtnum = 0; 67172b676d7Smrg 67272b676d7Smrg if(pPriv->dualHeadMode) crtnum = pSiSEnt->curxvcrtnum; 67372b676d7Smrg#endif 67472b676d7Smrg 67572b676d7Smrg /* 67672b676d7Smrg * SR06[7:6] 67772b676d7Smrg * Bit 7: Enable overlay 1 on CRT2 67872b676d7Smrg * Bit 6: Enable overlay 0 on CRT2 67972b676d7Smrg * SR32[7:6] 68072b676d7Smrg * Bit 7: DCLK/TCLK overlay 1 68172b676d7Smrg * 0=DCLK (overlay on CRT1) 68272b676d7Smrg * 1=TCLK (overlay on CRT2) 68372b676d7Smrg * Bit 6: DCLK/TCLK overlay 0 68472b676d7Smrg * 0=DCLK (overlay on CRT1) 68572b676d7Smrg * 1=TCLK (overlay on CRT2) 68672b676d7Smrg * 68772b676d7Smrg * On chipsets with two overlays, we can freely select and also 68872b676d7Smrg * have a mirror mode. However, we use overlay 0 for CRT1 and 68972b676d7Smrg * overlay 1 for CRT2. 69072b676d7Smrg * ATTENTION: CRT2 can only take up to 1 (one) overlay. Setting 69172b676d7Smrg * SR06/32 to 0xc0 DOES NOT WORK. THAT'S CONFIRMED. 69272b676d7Smrg * Therefore, we use overlay 0 on CRT2 if in SINGLE2 mode. 69372b676d7Smrg * 69472b676d7Smrg * For chipsets with only one overlay, user must choose whether 69572b676d7Smrg * to display the overlay on CRT1 or CRT2 by setting XvOnCRT2 69672b676d7Smrg * to TRUE (CRT2) or FALSE (CRT1). The driver does this auto- 69772b676d7Smrg * matically if only CRT1 or only CRT2 is used. 69872b676d7Smrg */ 69972b676d7Smrg#ifdef UNLOCK_ALWAYS 70072b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 70172b676d7Smrg#endif 70272b676d7Smrg 70372b676d7Smrg switch (pPriv->displayMode) 70472b676d7Smrg { 70572b676d7Smrg case DISPMODE_SINGLE1: /* CRT1-only mode: */ 70672b676d7Smrg if(pPriv->hasTwoOverlays) { 70772b676d7Smrg if(pPriv->dualHeadMode) { 70872b676d7Smrg setsrregmask(pSiS, 0x06, 0x00, 0x40); /* overlay 0 -> CRT1 */ 70972b676d7Smrg setsrregmask(pSiS, 0x32, 0x00, 0x40); 71072b676d7Smrg } else { 71172b676d7Smrg setsrregmask(pSiS, 0x06, 0x00, 0xc0); /* both overlays -> CRT1 */ 71272b676d7Smrg setsrregmask(pSiS, 0x32, 0x00, 0xc0); 71372b676d7Smrg } 71472b676d7Smrg } else { 71572b676d7Smrg#ifdef SISDUALHEAD 71672b676d7Smrg if((!pPriv->dualHeadMode) || (crtnum == 0)) { 71772b676d7Smrg#endif 71872b676d7Smrg setsrregmask(pSiS, 0x06, 0x00, 0xc0); /* only overlay -> CRT1 */ 71972b676d7Smrg setsrregmask(pSiS, 0x32, 0x00, 0xc0); 72072b676d7Smrg#ifdef SISDUALHEAD 72172b676d7Smrg } 72272b676d7Smrg#endif 72372b676d7Smrg } 72472b676d7Smrg break; 72572b676d7Smrg 72672b676d7Smrg case DISPMODE_SINGLE2: /* CRT2-only mode: */ 72772b676d7Smrg if(pPriv->hasTwoOverlays) { 72872b676d7Smrg if(pPriv->dualHeadMode) { 72972b676d7Smrg setsrregmask(pSiS, 0x06, 0x80, 0x80); /* overlay 1 -> CRT2 */ 73072b676d7Smrg setsrregmask(pSiS, 0x32, 0x80, 0x80); 73172b676d7Smrg } else { 73272b676d7Smrg setsrregmask(pSiS, 0x06, 0x40, 0xc0); /* overlay 0 -> CRT2 */ 73372b676d7Smrg setsrregmask(pSiS, 0x32, 0xc0, 0xc0); /* (although both clocks for CRT2!) */ 73472b676d7Smrg } 73572b676d7Smrg } else { 73672b676d7Smrg#ifdef SISDUALHEAD 73772b676d7Smrg if((!pPriv->dualHeadMode) || (crtnum == 1)) { 73872b676d7Smrg#endif 73972b676d7Smrg if(pSiS->MiscFlags & MISC_SIS760ONEOVERLAY) { 74072b676d7Smrg setsrregmask(pSiS, 0x06, 0x40, 0xc0); /* overlay 0 -> CRT2 */ 74172b676d7Smrg setsrregmask(pSiS, 0x32, 0xc0, 0xc0); /* (although both clocks for CRT2!) */ 74272b676d7Smrg } else { 74372b676d7Smrg setsrregmask(pSiS, 0x06, 0x40, 0xc0); /* only overlay -> CRT2 */ 74472b676d7Smrg setsrregmask(pSiS, 0x32, 0x40, 0xc0); 74572b676d7Smrg } 74672b676d7Smrg#ifdef SISDUALHEAD 74772b676d7Smrg } 74872b676d7Smrg#endif 74972b676d7Smrg } 75072b676d7Smrg break; 75172b676d7Smrg 75272b676d7Smrg case DISPMODE_MIRROR: /* CRT1+CRT2-mode: (only on chips with 2 overlays) */ 75372b676d7Smrg default: 75472b676d7Smrg setsrregmask(pSiS, 0x06, 0x80, 0xc0); /* overlay 0 -> CRT1, overlay 1 -> CRT2 */ 75572b676d7Smrg setsrregmask(pSiS, 0x32, 0x80, 0xc0); 75672b676d7Smrg break; 75772b676d7Smrg } 75872b676d7Smrg} 75972b676d7Smrg 76072b676d7Smrgstatic void 76172b676d7Smrgset_hastwooverlays(SISPtr pSiS, SISPortPrivPtr pPriv) 76272b676d7Smrg{ 76372b676d7Smrg int temp, watchdog; 76472b676d7Smrg 76572b676d7Smrg if(pSiS->hasTwoOverlays) { 76672b676d7Smrg if(pSiS->MiscFlags & MISC_SIS760ONEOVERLAY) { 76772b676d7Smrg if(pPriv->hasTwoOverlays) { 76872b676d7Smrg /* Disable overlay 1 on change */ 76972b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, 0x01); 77072b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x01); 77172b676d7Smrg temp = getvideoreg(pSiS,Index_VI_Control_Misc0); 77272b676d7Smrg if(temp & 0x02) { 77372b676d7Smrg watchdog = WATCHDOG_DELAY; 77472b676d7Smrg while((!vblank_active_CRT2(pSiS, pPriv)) && --watchdog); 77572b676d7Smrg watchdog = WATCHDOG_DELAY; 77672b676d7Smrg while(vblank_active_CRT2(pSiS, pPriv) && --watchdog); 77772b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02); 77872b676d7Smrg } 77972b676d7Smrg } 78072b676d7Smrg pPriv->hasTwoOverlays = FALSE; 78172b676d7Smrg } else { 78272b676d7Smrg pPriv->hasTwoOverlays = TRUE; 78372b676d7Smrg } 78472b676d7Smrg } else { 78572b676d7Smrg pPriv->hasTwoOverlays = FALSE; 78672b676d7Smrg } 78772b676d7Smrg} 78872b676d7Smrg 78972b676d7Smrgstatic void 79072b676d7Smrgset_allowswitchcrt(SISPtr pSiS, SISPortPrivPtr pPriv) 79172b676d7Smrg{ 79272b676d7Smrg if(pPriv->hasTwoOverlays) { 79372b676d7Smrg pPriv->AllowSwitchCRT = FALSE; 79472b676d7Smrg } else if((!(pSiS->VBFlags & DISPTYPE_DISP1)) || (!(pSiS->VBFlags & DISPTYPE_DISP2))) { 79572b676d7Smrg pPriv->AllowSwitchCRT = FALSE; 79672b676d7Smrg if(!(pSiS->VBFlags & DISPTYPE_DISP1)) pPriv->crtnum = 1; 79772b676d7Smrg else pPriv->crtnum = 0; 79872b676d7Smrg } else { 79972b676d7Smrg pPriv->AllowSwitchCRT = TRUE; 80072b676d7Smrg } 80172b676d7Smrg} 80272b676d7Smrg 80372b676d7Smrgstatic void 80472b676d7Smrgset_maxencoding(SISPtr pSiS, SISPortPrivPtr pPriv) 80572b676d7Smrg{ 80672b676d7Smrg int half; 80772b676d7Smrg 80872b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA) { 80972b676d7Smrg DummyEncoding.width = IMAGE_MAX_WIDTH_300; 81072b676d7Smrg DummyEncoding.height = IMAGE_MAX_HEIGHT_300; 81172b676d7Smrg } else { 81272b676d7Smrg DummyEncoding.width = IMAGE_MAX_WIDTH_315; 81372b676d7Smrg DummyEncoding.height = IMAGE_MAX_HEIGHT_315; 81472b676d7Smrg half = IMAGE_MAX_WIDTH_315 >> 1; 81572b676d7Smrg if(pPriv->is661741760) { 81672b676d7Smrg half = 768 * 2; 81772b676d7Smrg } else if(pPriv->is340) { /* 2 overlays? */ 81872b676d7Smrg DummyEncoding.width = IMAGE_MAX_WIDTH_340; 81972b676d7Smrg half = 1280; /* ? */ 82072b676d7Smrg } else if(pPriv->is761) { 82172b676d7Smrg DummyEncoding.width = IMAGE_MAX_WIDTH_761; 82272b676d7Smrg half = 1920; /* ? */ 82372b676d7Smrg } 82472b676d7Smrg if(pPriv->hasTwoOverlays) { 82572b676d7Smrg#ifdef SISDUALHEAD 82672b676d7Smrg if(pSiS->DualHeadMode) { 82772b676d7Smrg DummyEncoding.width = half; 82872b676d7Smrg } else 82972b676d7Smrg#endif 83072b676d7Smrg#ifdef SISMERGED 83172b676d7Smrg if(pSiS->MergedFB) { 83272b676d7Smrg DummyEncoding.width = half; 83372b676d7Smrg } else 83472b676d7Smrg#endif 83572b676d7Smrg if(pPriv->displayMode == DISPMODE_MIRROR) { 83672b676d7Smrg DummyEncoding.width = half; 83772b676d7Smrg } 83872b676d7Smrg } 83972b676d7Smrg } 84072b676d7Smrg} 84172b676d7Smrg 84272b676d7Smrg/********************************* 84372b676d7Smrg * ResetXvDisplay() * 84472b676d7Smrg *********************************/ 84572b676d7Smrg 84672b676d7Smrgstatic void 84772b676d7SmrgSISResetXvDisplay(ScrnInfoPtr pScrn) 84872b676d7Smrg{ 84972b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 85072b676d7Smrg SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn); 85172b676d7Smrg 85272b676d7Smrg if(!pPriv) return; 85372b676d7Smrg 85472b676d7Smrg set_hastwooverlays(pSiS, pPriv); 85572b676d7Smrg set_allowswitchcrt(pSiS, pPriv); 85672b676d7Smrg set_dispmode(pScrn, pPriv); 85772b676d7Smrg set_maxencoding(pSiS, pPriv); 85872b676d7Smrg} 85972b676d7Smrg 86072b676d7Smrg/********************************* 86172b676d7Smrg * SetupImageVideo() * 86272b676d7Smrg *********************************/ 86372b676d7Smrg 86472b676d7Smrgstatic XF86VideoAdaptorPtr 86572b676d7SmrgSISSetupImageVideo(ScreenPtr pScreen) 86672b676d7Smrg{ 86774c14cd6Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 86872b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 86972b676d7Smrg XF86VideoAdaptorPtr adapt; 87072b676d7Smrg SISPortPrivPtr pPriv; 87172b676d7Smrg 87272b676d7Smrg#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,1,99,1,0) 87372b676d7Smrg XAAInfoRecPtr pXAA = pSiS->AccelInfoPtr; 87472b676d7Smrg 87572b676d7Smrg if(!pXAA || !pXAA->FillSolidRects) { 87672b676d7Smrg return NULL; 87772b676d7Smrg } 87872b676d7Smrg#endif 87972b676d7Smrg 88074c14cd6Smrg if(!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + 88172b676d7Smrg sizeof(SISPortPrivRec) + 88272b676d7Smrg sizeof(DevUnion)))) { 88372b676d7Smrg return NULL; 88472b676d7Smrg } 88572b676d7Smrg 88672b676d7Smrg adapt->type = XvWindowMask | XvInputMask | XvImageMask; 88772b676d7Smrg adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; 88872b676d7Smrg adapt->name = "SIS 300/315/330 series Video Overlay"; 88972b676d7Smrg adapt->nEncodings = 1; 89072b676d7Smrg adapt->pEncodings = &DummyEncoding; 89172b676d7Smrg 89272b676d7Smrg adapt->nFormats = NUM_FORMATS; 89372b676d7Smrg adapt->pFormats = SISFormats; 89472b676d7Smrg adapt->nPorts = 1; 89572b676d7Smrg adapt->pPortPrivates = (DevUnion*)(&adapt[1]); 89672b676d7Smrg 89772b676d7Smrg pPriv = (SISPortPrivPtr)(&adapt->pPortPrivates[1]); 89872b676d7Smrg 89972b676d7Smrg pPriv->videoStatus = 0; 90072b676d7Smrg pPriv->currentBuf = 0; 90172b676d7Smrg pPriv->handle = NULL; 90272b676d7Smrg pPriv->grabbedByV4L= FALSE; 90372b676d7Smrg pPriv->NoOverlay = FALSE; 90472b676d7Smrg pPriv->PrevOverlay = FALSE; 90572b676d7Smrg pPriv->is661741760 = ((pSiS->ChipType >= SIS_661) && 90672b676d7Smrg (pSiS->ChipType <= SIS_760)) ? TRUE : FALSE; 90772b676d7Smrg pPriv->is760 = (pSiS->ChipType == SIS_760) ? TRUE : FALSE; 90872b676d7Smrg pPriv->is761 = (pSiS->ChipType == SIS_761) ? TRUE : FALSE; 90972b676d7Smrg pPriv->is340 = (pSiS->Chipset == PCI_CHIP_SIS340) ? TRUE : FALSE; 91072b676d7Smrg pPriv->isXGI = (pSiS->Chipset == PCI_CHIP_XGIXG20 || 91172b676d7Smrg pSiS->Chipset == PCI_CHIP_XGIXG40) ? TRUE : FALSE; 91272b676d7Smrg 91372b676d7Smrg /* Setup chipset type helpers */ 91472b676d7Smrg set_hastwooverlays(pSiS, pPriv); 91572b676d7Smrg set_allowswitchcrt(pSiS, pPriv); 91672b676d7Smrg 91772b676d7Smrg pPriv->havetapscaler = FALSE; 91872b676d7Smrg if(pPriv->is340 || pPriv->is761 || pPriv->isXGI) { 91972b676d7Smrg pPriv->havetapscaler = TRUE; 92072b676d7Smrg } 92172b676d7Smrg 92272b676d7Smrg adapt->pPortPrivates[0].ptr = (pointer)(pPriv); 92372b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA) { 92472b676d7Smrg adapt->nImages = NUM_IMAGES_300; 92572b676d7Smrg adapt->pAttributes = SISAttributes_300; 92672b676d7Smrg adapt->nAttributes = SiSCountAttributes(&SISAttributes_300[0]); 92772b676d7Smrg } else { 92872b676d7Smrg if(pSiS->ChipType >= SIS_330) { 92972b676d7Smrg adapt->nImages = NUM_IMAGES_330; 93072b676d7Smrg } else { 93172b676d7Smrg adapt->nImages = NUM_IMAGES_315; 93272b676d7Smrg } 93372b676d7Smrg adapt->pAttributes = SISAttributes_315; 93472b676d7Smrg adapt->nAttributes = SiSCountAttributes(&SISAttributes_315[0]); 93572b676d7Smrg if((pSiS->hasTwoOverlays) && (!(pSiS->SiS_SD2_Flags & SiS_SD2_SUPPORT760OO))) { 93672b676d7Smrg adapt->nAttributes--; 93772b676d7Smrg } 93872b676d7Smrg } 93972b676d7Smrg 94072b676d7Smrg adapt->pImages = SISImages; 94172b676d7Smrg adapt->PutVideo = NULL; 94272b676d7Smrg adapt->PutStill = NULL; 94372b676d7Smrg adapt->GetVideo = NULL; 94472b676d7Smrg adapt->GetStill = NULL; 94572b676d7Smrg adapt->StopVideo = SISStopVideo; 94672b676d7Smrg adapt->SetPortAttribute = SISSetPortAttribute; 94772b676d7Smrg adapt->GetPortAttribute = SISGetPortAttribute; 94872b676d7Smrg adapt->QueryBestSize = SISQueryBestSize; 94972b676d7Smrg adapt->PutImage = SISPutImage; 95072b676d7Smrg adapt->QueryImageAttributes = SISQueryImageAttributes; 95172b676d7Smrg 95272b676d7Smrg /* gotta uninit this someplace */ 95372b676d7Smrg#if defined(REGION_NULL) 95472b676d7Smrg REGION_NULL(pScreen, &pPriv->clip); 95572b676d7Smrg#else 95672b676d7Smrg REGION_INIT(pScreen, &pPriv->clip, NullBox, 0); 95772b676d7Smrg#endif 95872b676d7Smrg 95972b676d7Smrg pSiS->adaptor = adapt; 96072b676d7Smrg 96172b676d7Smrg pSiS->xvBrightness = MAKE_ATOM(sisxvbrightness); 96272b676d7Smrg pSiS->xvContrast = MAKE_ATOM(sisxvcontrast); 96372b676d7Smrg pSiS->xvColorKey = MAKE_ATOM(sisxvcolorkey); 96472b676d7Smrg pSiS->xvSaturation = MAKE_ATOM(sisxvsaturation); 96572b676d7Smrg pSiS->xvHue = MAKE_ATOM(sisxvhue); 96672b676d7Smrg pSiS->xvSwitchCRT = MAKE_ATOM(sisxvswitchcrt); 96772b676d7Smrg pSiS->xvAutopaintColorKey = MAKE_ATOM(sisxvautopaintcolorkey); 96872b676d7Smrg pSiS->xvSetDefaults = MAKE_ATOM(sisxvsetdefaults); 96972b676d7Smrg pSiS->xvDisableGfx = MAKE_ATOM(sisxvdisablegfx); 97072b676d7Smrg pSiS->xvDisableGfxLR = MAKE_ATOM(sisxvdisablegfxlr); 97172b676d7Smrg pSiS->xvTVXPosition = MAKE_ATOM(sisxvtvxposition); 97272b676d7Smrg pSiS->xvTVYPosition = MAKE_ATOM(sisxvtvyposition); 97372b676d7Smrg pSiS->xvGammaRed = MAKE_ATOM(sisxvgammared); 97472b676d7Smrg pSiS->xvGammaGreen = MAKE_ATOM(sisxvgammagreen); 97572b676d7Smrg pSiS->xvGammaBlue = MAKE_ATOM(sisxvgammablue); 97672b676d7Smrg pSiS->xvDisableColorkey = MAKE_ATOM(sisxvdisablecolorkey); 97772b676d7Smrg pSiS->xvUseChromakey = MAKE_ATOM(sisxvusechromakey); 97872b676d7Smrg pSiS->xvInsideChromakey = MAKE_ATOM(sisxvinsidechromakey); 97972b676d7Smrg pSiS->xvYUVChromakey = MAKE_ATOM(sisxvyuvchromakey); 98072b676d7Smrg pSiS->xvChromaMin = MAKE_ATOM(sisxvchromamin); 98172b676d7Smrg pSiS->xvChromaMax = MAKE_ATOM(sisxvchromamax); 98272b676d7Smrg#ifdef SISDEINT 98372b676d7Smrg pSiS->xvdeintmeth = MAKE_ATOM(sisxvdeinterlace); 98472b676d7Smrg#endif 98572b676d7Smrg#ifdef XV_SD_DEPRECATED 98672b676d7Smrg pSiS->xv_QVF = MAKE_ATOM(sisxvqueryvbflags); 98772b676d7Smrg pSiS->xv_GDV = MAKE_ATOM(sisxvsdgetdriverversion); 98872b676d7Smrg pSiS->xv_GHI = MAKE_ATOM(sisxvsdgethardwareinfo); 98972b676d7Smrg pSiS->xv_GBI = MAKE_ATOM(sisxvsdgetbusid); 99072b676d7Smrg pSiS->xv_QVV = MAKE_ATOM(sisxvsdqueryvbflagsversion); 99172b676d7Smrg pSiS->xv_GSF = MAKE_ATOM(sisxvsdgetsdflags); 99272b676d7Smrg pSiS->xv_GSF2 = MAKE_ATOM(sisxvsdgetsdflags2); 99372b676d7Smrg pSiS->xv_USD = MAKE_ATOM(sisxvsdunlocksisdirect); 99472b676d7Smrg pSiS->xv_SVF = MAKE_ATOM(sisxvsdsetvbflags); 99572b676d7Smrg pSiS->xv_QDD = MAKE_ATOM(sisxvsdquerydetecteddevices); 99672b676d7Smrg pSiS->xv_CT1 = MAKE_ATOM(sisxvsdcrt1status); 99772b676d7Smrg pSiS->xv_CMD = MAKE_ATOM(sisxvsdcheckmodeindexforcrt2); 99872b676d7Smrg pSiS->xv_CMDR = MAKE_ATOM(sisxvsdresultcheckmodeindexforcrt2); 99972b676d7Smrg pSiS->xv_RDT = MAKE_ATOM(sisxvsdredetectcrt2); 100072b676d7Smrg pSiS->xv_TAF = MAKE_ATOM(sisxvsdsisantiflicker); 100172b676d7Smrg pSiS->xv_TSA = MAKE_ATOM(sisxvsdsissaturation); 100272b676d7Smrg pSiS->xv_TEE = MAKE_ATOM(sisxvsdsisedgeenhance); 100372b676d7Smrg pSiS->xv_COC = MAKE_ATOM(sisxvsdsiscolcalibc); 100472b676d7Smrg pSiS->xv_COF = MAKE_ATOM(sisxvsdsiscolcalibf); 100572b676d7Smrg pSiS->xv_CFI = MAKE_ATOM(sisxvsdsiscfilter); 100672b676d7Smrg pSiS->xv_YFI = MAKE_ATOM(sisxvsdsisyfilter); 100772b676d7Smrg pSiS->xv_TCO = MAKE_ATOM(sisxvsdchcontrast); 100872b676d7Smrg pSiS->xv_TTE = MAKE_ATOM(sisxvsdchtextenhance); 100972b676d7Smrg pSiS->xv_TCF = MAKE_ATOM(sisxvsdchchromaflickerfilter); 101072b676d7Smrg pSiS->xv_TLF = MAKE_ATOM(sisxvsdchlumaflickerfilter); 101172b676d7Smrg pSiS->xv_TCC = MAKE_ATOM(sisxvsdchcvbscolor); 101272b676d7Smrg pSiS->xv_OVR = MAKE_ATOM(sisxvsdchoverscan); 101372b676d7Smrg pSiS->xv_SGA = MAKE_ATOM(sisxvsdenablegamma); 101472b676d7Smrg pSiS->xv_TXS = MAKE_ATOM(sisxvsdtvxscale); 101572b676d7Smrg pSiS->xv_TYS = MAKE_ATOM(sisxvsdtvyscale); 101672b676d7Smrg pSiS->xv_GSS = MAKE_ATOM(sisxvsdgetscreensize); 101772b676d7Smrg pSiS->xv_BRR = MAKE_ATOM(sisxvsdstorebrir); 101872b676d7Smrg pSiS->xv_BRG = MAKE_ATOM(sisxvsdstorebrig); 101972b676d7Smrg pSiS->xv_BRB = MAKE_ATOM(sisxvsdstorebrib); 102072b676d7Smrg pSiS->xv_PBR = MAKE_ATOM(sisxvsdstorepbrir); 102172b676d7Smrg pSiS->xv_PBG = MAKE_ATOM(sisxvsdstorepbrig); 102272b676d7Smrg pSiS->xv_PBB = MAKE_ATOM(sisxvsdstorepbrib); 102372b676d7Smrg pSiS->xv_BRR2 = MAKE_ATOM(sisxvsdstorebrir2); 102472b676d7Smrg pSiS->xv_BRG2 = MAKE_ATOM(sisxvsdstorebrig2); 102572b676d7Smrg pSiS->xv_BRB2 = MAKE_ATOM(sisxvsdstorebrib2); 102672b676d7Smrg pSiS->xv_PBR2 = MAKE_ATOM(sisxvsdstorepbrir2); 102772b676d7Smrg pSiS->xv_PBG2 = MAKE_ATOM(sisxvsdstorepbrig2); 102872b676d7Smrg pSiS->xv_PBB2 = MAKE_ATOM(sisxvsdstorepbrib2); 102972b676d7Smrg pSiS->xv_GARC2 = MAKE_ATOM(sisxvsdstoregarc2); 103072b676d7Smrg pSiS->xv_GAGC2 = MAKE_ATOM(sisxvsdstoregagc2); 103172b676d7Smrg pSiS->xv_GABC2 = MAKE_ATOM(sisxvsdstoregabc2); 103272b676d7Smrg pSiS->xv_BRRC2 = MAKE_ATOM(sisxvsdstorebrirc2); 103372b676d7Smrg pSiS->xv_BRGC2 = MAKE_ATOM(sisxvsdstorebrigc2); 103472b676d7Smrg pSiS->xv_BRBC2 = MAKE_ATOM(sisxvsdstorebribc2); 103572b676d7Smrg pSiS->xv_PBRC2 = MAKE_ATOM(sisxvsdstorepbrirc2); 103672b676d7Smrg pSiS->xv_PBGC2 = MAKE_ATOM(sisxvsdstorepbrigc2); 103772b676d7Smrg pSiS->xv_PBBC2 = MAKE_ATOM(sisxvsdstorepbribc2); 103872b676d7Smrg pSiS->xv_SHC = MAKE_ATOM(sisxvsdhidehwcursor); 103972b676d7Smrg pSiS->xv_PMD = MAKE_ATOM(sisxvsdpanelmode); 104072b676d7Smrg#ifdef TWDEBUG 104172b676d7Smrg pSiS->xv_STR = MAKE_ATOM(sisxvsetreg); 104272b676d7Smrg#endif 104372b676d7Smrg#endif /* XV_SD_DEPRECATED */ 104472b676d7Smrg#ifdef SIS_CP 104572b676d7Smrg SIS_CP_VIDEO_ATOMS 104672b676d7Smrg#endif 104772b676d7Smrg 104872b676d7Smrg pSiS->xv_sisdirectunlocked = 0; 104972b676d7Smrg#ifdef XV_SD_DEPRECATED 105072b676d7Smrg pSiS->xv_sd_result = 0; 105172b676d7Smrg#endif 105272b676d7Smrg 105372b676d7Smrg /* 300 series require double words for addresses and pitches, 105472b676d7Smrg * 315/330 series require word. 105572b676d7Smrg */ 105672b676d7Smrg switch (pSiS->VGAEngine) { 105772b676d7Smrg case SIS_315_VGA: 105872b676d7Smrg pPriv->shiftValue = 1; 105972b676d7Smrg break; 106072b676d7Smrg case SIS_300_VGA: 106172b676d7Smrg default: 106272b676d7Smrg pPriv->shiftValue = 2; 106372b676d7Smrg break; 106472b676d7Smrg } 106572b676d7Smrg 106672b676d7Smrg /* Set displayMode according to VBFlags */ 106772b676d7Smrg set_dispmode(pScrn, pPriv); 106872b676d7Smrg 106972b676d7Smrg /* Now for the linebuffer stuff. 107072b676d7Smrg * All chipsets have a certain number of linebuffers, each of a certain 107172b676d7Smrg * size. The number of buffers is per overlay. 107272b676d7Smrg * Chip number size max video size 107372b676d7Smrg * 300 2 ? 720x576 107472b676d7Smrg * 630/730 2 ? 720x576 107572b676d7Smrg * 315 2 960? 1920x1080 107672b676d7Smrg * 550 2? 960? 1920x1080? 107772b676d7Smrg * 650/740 2 960 ("120x128") 1920x1080 107872b676d7Smrg * M650/651.. 4 480 1920x1080 107972b676d7Smrg * 330 2 960 1920x1080 108072b676d7Smrg * 661/741/760 4 768 1920x1080 108172b676d7Smrg * 340 4 1280? 1920x1080? 108272b676d7Smrg * 761 4 1536? 1920x1080? 108372b676d7Smrg * The unit of size is unknown; I just know that a size of 480 limits 108472b676d7Smrg * the video source width to 384. Beyond that, line buffers must be 108572b676d7Smrg * merged (otherwise the video output is garbled). 108672b676d7Smrg * To use the maximum width (eg 1920x1080 on the 315 series, including 108772b676d7Smrg * the M650, 651 and later), *all* line buffers must be merged. Hence, 108872b676d7Smrg * we can only use one overlay. This should be set up for modes where 108972b676d7Smrg * either only CRT1 or only CRT2 is used. 109072b676d7Smrg * If both overlays are going to be used (such as in modes were both 109172b676d7Smrg * CRT1 and CRT2 are active), we are limited to the half of the 109272b676d7Smrg * maximum width, or 1536 on 661/741/760. 109372b676d7Smrg * There is a known hardware problem with the 760 and 761 if the video 109472b676d7Smrg * data is in the UMA area: The memory access latency is too big to 109572b676d7Smrg * allow two overlays under some circumstances. Therefore, we must 109672b676d7Smrg * support switching between hasTwoOverlays and !hasTwoOverlays on 109772b676d7Smrg * the fly. 109872b676d7Smrg */ 109972b676d7Smrg 110072b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA) { 110172b676d7Smrg pPriv->linebufmask = 0x11; 110272b676d7Smrg pPriv->linebufMergeLimit = 384; 110372b676d7Smrg } else { 110472b676d7Smrg pPriv->linebufmask = 0xb1; 110572b676d7Smrg pPriv->linebufMergeLimit = 384; /* should be 480 */ 110672b676d7Smrg if(pPriv->is661741760) { 110772b676d7Smrg pPriv->linebufMergeLimit = 576; /* should be 768 */ 110872b676d7Smrg } else if(pPriv->is340) { 110972b676d7Smrg pPriv->linebufMergeLimit = 1280; /* should be 1280 */ 111072b676d7Smrg } else if(pPriv->is761) { 111172b676d7Smrg pPriv->linebufMergeLimit = 1280; /* should be 1536 */ 111272b676d7Smrg } else if(pPriv->isXGI) { 111372b676d7Smrg pPriv->linebufMergeLimit = 1280; /* FIXME */ 111472b676d7Smrg } else if(!(pPriv->hasTwoOverlays)) { 111572b676d7Smrg pPriv->linebufMergeLimit = 720; /* should be 960 */ 111672b676d7Smrg } 111772b676d7Smrg /* No special treatment for 760/761 required */ 111872b676d7Smrg } 111972b676d7Smrg 112072b676d7Smrg set_maxencoding(pSiS, pPriv); 112172b676d7Smrg 112272b676d7Smrg /* Reset the properties to their defaults */ 112372b676d7Smrg SISSetPortDefaults(pScrn, pPriv); 112472b676d7Smrg 112572b676d7Smrg /* Set SR(06, 32) registers according to DISPMODE */ 112672b676d7Smrg set_disptype_regs(pScrn, pPriv); 112772b676d7Smrg 112872b676d7Smrg SISResetVideo(pScrn); 112972b676d7Smrg pSiS->ResetXv = SISResetVideo; 113072b676d7Smrg pSiS->ResetXvDisplay = SISResetXvDisplay; 113172b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 113272b676d7Smrg pSiS->ResetXvGamma = SISResetXvGamma; 113372b676d7Smrg } 113472b676d7Smrg 113572b676d7Smrg return adapt; 113672b676d7Smrg} 113772b676d7Smrg 113872b676d7Smrg#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,3,99,3,0) 113972b676d7Smrgstatic Bool 114072b676d7SmrgRegionsEqual(RegionPtr A, RegionPtr B) 114172b676d7Smrg{ 114272b676d7Smrg int *dataA, *dataB; 114372b676d7Smrg int num; 114472b676d7Smrg 114572b676d7Smrg num = REGION_NUM_RECTS(A); 114672b676d7Smrg if(num != REGION_NUM_RECTS(B)) 114772b676d7Smrg return FALSE; 114872b676d7Smrg 114972b676d7Smrg if((A->extents.x1 != B->extents.x1) || 115072b676d7Smrg (A->extents.x2 != B->extents.x2) || 115172b676d7Smrg (A->extents.y1 != B->extents.y1) || 115272b676d7Smrg (A->extents.y2 != B->extents.y2)) 115372b676d7Smrg return FALSE; 115472b676d7Smrg 115572b676d7Smrg dataA = (int*)REGION_RECTS(A); 115672b676d7Smrg dataB = (int*)REGION_RECTS(B); 115772b676d7Smrg 115872b676d7Smrg while(num--) { 115972b676d7Smrg if((dataA[0] != dataB[0]) || (dataA[1] != dataB[1])) 116072b676d7Smrg return FALSE; 116172b676d7Smrg dataA += 2; 116272b676d7Smrg dataB += 2; 116372b676d7Smrg } 116472b676d7Smrg 116572b676d7Smrg return TRUE; 116672b676d7Smrg} 116772b676d7Smrg#endif 116872b676d7Smrg 116972b676d7Smrg/********************************* 117072b676d7Smrg * SetPortAttribute() * 117172b676d7Smrg *********************************/ 117272b676d7Smrg 117372b676d7Smrgvoid 117472b676d7SmrgSISUpdateVideoParms(SISPtr pSiS, SISPortPrivPtr pPriv) 117572b676d7Smrg{ 117672b676d7Smrg set_hastwooverlays(pSiS, pPriv); 117772b676d7Smrg set_allowswitchcrt(pSiS, pPriv); 117872b676d7Smrg set_dispmode(pSiS->pScrn, pPriv); 117972b676d7Smrg set_maxencoding(pSiS, pPriv); 118072b676d7Smrg} 118172b676d7Smrg 118272b676d7Smrgstatic int 118372b676d7SmrgSISSetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, 118472b676d7Smrg INT32 value, pointer data) 118572b676d7Smrg{ 118672b676d7Smrg SISPortPrivPtr pPriv = (SISPortPrivPtr)data; 118772b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 118872b676d7Smrg#ifdef SISDUALHEAD 118972b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate;; 119072b676d7Smrg#endif 119172b676d7Smrg 119272b676d7Smrg if(attribute == pSiS->xvBrightness) { 119372b676d7Smrg if((value < -128) || (value > 127)) 119472b676d7Smrg return BadValue; 119572b676d7Smrg pPriv->brightness = value; 119672b676d7Smrg } else if(attribute == pSiS->xvContrast) { 119772b676d7Smrg if((value < 0) || (value > 7)) 119872b676d7Smrg return BadValue; 119972b676d7Smrg pPriv->contrast = value; 120072b676d7Smrg } else if(attribute == pSiS->xvColorKey) { 120172b676d7Smrg pPriv->colorKey = pSiS->colorKey = value; 120272b676d7Smrg REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 120372b676d7Smrg } else if(attribute == pSiS->xvAutopaintColorKey) { 120472b676d7Smrg if((value < 0) || (value > 1)) 120572b676d7Smrg return BadValue; 120672b676d7Smrg pPriv->autopaintColorKey = value; 120772b676d7Smrg } else if(attribute == pSiS->xvSetDefaults) { 120872b676d7Smrg SISSetPortDefaults(pScrn, pPriv); 120972b676d7Smrg } else if(attribute == pSiS->xvDisableGfx) { 121072b676d7Smrg if((value < 0) || (value > 1)) 121172b676d7Smrg return BadValue; 121272b676d7Smrg pPriv->disablegfx = value; 121372b676d7Smrg } else if(attribute == pSiS->xvDisableGfxLR) { 121472b676d7Smrg if((value < 0) || (value > 1)) 121572b676d7Smrg return BadValue; 121672b676d7Smrg pPriv->disablegfxlr = value; 121772b676d7Smrg } else if(attribute == pSiS->xvTVXPosition) { 121872b676d7Smrg if((value < -32) || (value > 32)) 121972b676d7Smrg return BadValue; 122072b676d7Smrg pPriv->tvxpos = value; 122172b676d7Smrg if(pSiS->xv_sisdirectunlocked) { 122272b676d7Smrg SiS_SetTVxposoffset(pScrn, pPriv->tvxpos); 122372b676d7Smrg pPriv->updatetvxpos = FALSE; 122472b676d7Smrg } else { 122572b676d7Smrg pSiS->tvxpos = pPriv->tvxpos; 122672b676d7Smrg#ifdef SISDUALHEAD 122772b676d7Smrg if(pPriv->dualHeadMode) pSiSEnt->tvxpos = pPriv->tvxpos; 122872b676d7Smrg#endif 122972b676d7Smrg pPriv->updatetvxpos = TRUE; 123072b676d7Smrg } 123172b676d7Smrg } else if(attribute == pSiS->xvTVYPosition) { 123272b676d7Smrg if((value < -32) || (value > 32)) return BadValue; 123372b676d7Smrg pPriv->tvypos = value; 123472b676d7Smrg if(pSiS->xv_sisdirectunlocked) { 123572b676d7Smrg SiS_SetTVyposoffset(pScrn, pPriv->tvypos); 123672b676d7Smrg pPriv->updatetvypos = FALSE; 123772b676d7Smrg } else { 123872b676d7Smrg pSiS->tvypos = pPriv->tvypos; 123972b676d7Smrg#ifdef SISDUALHEAD 124072b676d7Smrg if(pPriv->dualHeadMode) pSiSEnt->tvypos = pPriv->tvypos; 124172b676d7Smrg#endif 124272b676d7Smrg pPriv->updatetvypos = TRUE; 124372b676d7Smrg } 124472b676d7Smrg } else if(attribute == pSiS->xvDisableColorkey) { 124572b676d7Smrg if((value < 0) || (value > 1)) return BadValue; 124672b676d7Smrg pSiS->disablecolorkeycurrent = value; 124772b676d7Smrg } else if(attribute == pSiS->xvUseChromakey) { 124872b676d7Smrg if((value < 0) || (value > 1)) return BadValue; 124972b676d7Smrg pPriv->usechromakey = value; 125072b676d7Smrg } else if(attribute == pSiS->xvInsideChromakey) { 125172b676d7Smrg if((value < 0) || (value > 1)) return BadValue; 125272b676d7Smrg pPriv->insidechromakey = value; 125372b676d7Smrg } else if(attribute == pSiS->xvYUVChromakey) { 125472b676d7Smrg if((value < 0) || (value > 1)) return BadValue; 125572b676d7Smrg pPriv->yuvchromakey = value; 125672b676d7Smrg } else if(attribute == pSiS->xvChromaMin) { 125772b676d7Smrg pPriv->chromamin = value; 125872b676d7Smrg } else if(attribute == pSiS->xvChromaMax) { 125972b676d7Smrg pPriv->chromamax = value; 126072b676d7Smrg#ifdef SISDEINT 126172b676d7Smrg } else if(attribute == pSiS->xvdeintmeth) { 126272b676d7Smrg if(value < 0) value = 0; 126372b676d7Smrg if(value > 4) value = 4; 126472b676d7Smrg pPriv->deinterlacemethod = value; 126572b676d7Smrg#endif 126672b676d7Smrg#ifdef SIS_CP 126772b676d7Smrg SIS_CP_VIDEO_SETATTRIBUTE 126872b676d7Smrg#endif 126972b676d7Smrg } else if(attribute == pSiS->xvHue) { 127072b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 127172b676d7Smrg if((value < -8) || (value > 7)) return BadValue; 127272b676d7Smrg pPriv->hue = value; 127372b676d7Smrg } else return BadMatch; 127472b676d7Smrg } else if(attribute == pSiS->xvSaturation) { 127572b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 127672b676d7Smrg if((value < -7) || (value > 7)) return BadValue; 127772b676d7Smrg pPriv->saturation = value; 127872b676d7Smrg } else return BadMatch; 127972b676d7Smrg } else if(attribute == pSiS->xvGammaRed) { 128072b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 128172b676d7Smrg if((value < 100) || (value > 10000)) return BadValue; 128272b676d7Smrg pSiS->XvGammaRed = value; 128372b676d7Smrg SiSUpdateXvGamma(pSiS, pPriv); 128472b676d7Smrg } else return BadMatch; 128572b676d7Smrg } else if(attribute == pSiS->xvGammaGreen) { 128672b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 128772b676d7Smrg if((value < 100) || (value > 10000)) return BadValue; 128872b676d7Smrg pSiS->XvGammaGreen = value; 128972b676d7Smrg SiSUpdateXvGamma(pSiS, pPriv); 129072b676d7Smrg } else return BadMatch; 129172b676d7Smrg } else if(attribute == pSiS->xvGammaBlue) { 129272b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 129372b676d7Smrg if((value < 100) || (value > 10000)) return BadValue; 129472b676d7Smrg pSiS->XvGammaBlue = value; 129572b676d7Smrg SiSUpdateXvGamma(pSiS, pPriv); 129672b676d7Smrg } else return BadMatch; 129772b676d7Smrg } else if(attribute == pSiS->xvSwitchCRT) { 129872b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 129972b676d7Smrg if(pPriv->AllowSwitchCRT) { 130072b676d7Smrg if((value < 0) || (value > 1)) 130172b676d7Smrg return BadValue; 130272b676d7Smrg pPriv->crtnum = value; 130372b676d7Smrg#ifdef SISDUALHEAD 130472b676d7Smrg if(pPriv->dualHeadMode) pSiSEnt->curxvcrtnum = value; 130572b676d7Smrg#endif 130672b676d7Smrg } 130772b676d7Smrg } else return BadMatch; 130872b676d7Smrg } else { 130972b676d7Smrg#ifdef XV_SD_DEPRECATED 131072b676d7Smrg return(SISSetPortUtilAttribute(pScrn, attribute, value, pPriv)); 131172b676d7Smrg#else 131272b676d7Smrg return BadMatch; 131372b676d7Smrg#endif 131472b676d7Smrg } 131572b676d7Smrg return Success; 131672b676d7Smrg} 131772b676d7Smrg 131872b676d7Smrg/********************************* 131972b676d7Smrg * GetPortAttribute() * 132072b676d7Smrg *********************************/ 132172b676d7Smrg 132272b676d7Smrgstatic int 132372b676d7SmrgSISGetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, 132472b676d7Smrg INT32 *value, pointer data) 132572b676d7Smrg{ 132672b676d7Smrg SISPortPrivPtr pPriv = (SISPortPrivPtr)data; 132772b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 132872b676d7Smrg#ifdef SISDUALHEAD 132972b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate;; 133072b676d7Smrg#endif 133172b676d7Smrg 133272b676d7Smrg if(attribute == pSiS->xvBrightness) { 133372b676d7Smrg *value = pPriv->brightness; 133472b676d7Smrg } else if(attribute == pSiS->xvContrast) { 133572b676d7Smrg *value = pPriv->contrast; 133672b676d7Smrg } else if(attribute == pSiS->xvColorKey) { 133772b676d7Smrg *value = pPriv->colorKey; 133872b676d7Smrg } else if(attribute == pSiS->xvAutopaintColorKey) { 133972b676d7Smrg *value = (pPriv->autopaintColorKey) ? 1 : 0; 134072b676d7Smrg } else if(attribute == pSiS->xvDisableGfx) { 134172b676d7Smrg *value = (pPriv->disablegfx) ? 1 : 0; 134272b676d7Smrg } else if(attribute == pSiS->xvDisableGfxLR) { 134372b676d7Smrg *value = (pPriv->disablegfxlr) ? 1 : 0; 134472b676d7Smrg } else if(attribute == pSiS->xvTVXPosition) { 134572b676d7Smrg *value = SiS_GetTVxposoffset(pScrn); 134672b676d7Smrg } else if(attribute == pSiS->xvTVYPosition) { 134772b676d7Smrg *value = SiS_GetTVyposoffset(pScrn); 134872b676d7Smrg } else if(attribute == pSiS->xvDisableColorkey) { 134972b676d7Smrg *value = (pSiS->disablecolorkeycurrent) ? 1 : 0; 135072b676d7Smrg } else if(attribute == pSiS->xvUseChromakey) { 135172b676d7Smrg *value = (pPriv->usechromakey) ? 1 : 0; 135272b676d7Smrg } else if(attribute == pSiS->xvInsideChromakey) { 135372b676d7Smrg *value = (pPriv->insidechromakey) ? 1 : 0; 135472b676d7Smrg } else if(attribute == pSiS->xvYUVChromakey) { 135572b676d7Smrg *value = (pPriv->yuvchromakey) ? 1 : 0; 135672b676d7Smrg } else if(attribute == pSiS->xvChromaMin) { 135772b676d7Smrg *value = pPriv->chromamin; 135872b676d7Smrg } else if(attribute == pSiS->xvChromaMax) { 135972b676d7Smrg *value = pPriv->chromamax; 136072b676d7Smrg#ifdef SISDEINT 136172b676d7Smrg } else if(attribute == pSiS->xvdeintmeth) { 136272b676d7Smrg *value = pPriv->deinterlacemethod; 136372b676d7Smrg#endif 136472b676d7Smrg#ifdef SIS_CP 136572b676d7Smrg SIS_CP_VIDEO_GETATTRIBUTE 136672b676d7Smrg#endif 136772b676d7Smrg } else if(attribute == pSiS->xvHue) { 136872b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 136972b676d7Smrg *value = pPriv->hue; 137072b676d7Smrg } else return BadMatch; 137172b676d7Smrg } else if(attribute == pSiS->xvSaturation) { 137272b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 137372b676d7Smrg *value = pPriv->saturation; 137472b676d7Smrg } else return BadMatch; 137572b676d7Smrg } else if(attribute == pSiS->xvGammaRed) { 137672b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 137772b676d7Smrg *value = pSiS->XvGammaRed; 137872b676d7Smrg } else return BadMatch; 137972b676d7Smrg } else if(attribute == pSiS->xvGammaGreen) { 138072b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 138172b676d7Smrg *value = pSiS->XvGammaGreen; 138272b676d7Smrg } else return BadMatch; 138372b676d7Smrg } else if(attribute == pSiS->xvGammaBlue) { 138472b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 138572b676d7Smrg *value = pSiS->XvGammaBlue; 138672b676d7Smrg } else return BadMatch; 138772b676d7Smrg } else if(attribute == pSiS->xvSwitchCRT) { 138872b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 138972b676d7Smrg#ifdef SISDUALHEAD 139072b676d7Smrg if(pPriv->dualHeadMode) 139172b676d7Smrg *value = pSiSEnt->curxvcrtnum; 139272b676d7Smrg else 139372b676d7Smrg#endif 139472b676d7Smrg *value = pPriv->crtnum; 139572b676d7Smrg } else return BadMatch; 139672b676d7Smrg } else { 139772b676d7Smrg#ifdef XV_SD_DEPRECATED 139872b676d7Smrg return(SISGetPortUtilAttribute(pScrn, attribute, value, pPriv)); 139972b676d7Smrg#else 140072b676d7Smrg return BadMatch; 140172b676d7Smrg#endif 140272b676d7Smrg } 140372b676d7Smrg return Success; 140472b676d7Smrg} 140572b676d7Smrg 140672b676d7Smrg/********************************* 140772b676d7Smrg * QueryBestSize() * 140872b676d7Smrg *********************************/ 140972b676d7Smrg 141072b676d7Smrgstatic void 141172b676d7SmrgSISQueryBestSize( 141272b676d7Smrg ScrnInfoPtr pScrn, 141372b676d7Smrg Bool motion, 141472b676d7Smrg short vid_w, short vid_h, 141572b676d7Smrg short drw_w, short drw_h, 141672b676d7Smrg unsigned int *p_w, unsigned int *p_h, 141772b676d7Smrg pointer data 141872b676d7Smrg){ 141972b676d7Smrg *p_w = drw_w; 142072b676d7Smrg *p_h = drw_h; 142172b676d7Smrg} 142272b676d7Smrg 142372b676d7Smrg/********************************* 142472b676d7Smrg * Calc scaling factor * 142572b676d7Smrg *********************************/ 142672b676d7Smrg 142772b676d7Smrgstatic void 142872b676d7Smrgcalc_scale_factor(SISOverlayPtr pOverlay, ScrnInfoPtr pScrn, 142972b676d7Smrg SISPortPrivPtr pPriv, int index, int iscrt2) 143072b676d7Smrg{ 143172b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 143272b676d7Smrg CARD32 I=0,mult=0; 143372b676d7Smrg int flag=0, flag2=0; 143472b676d7Smrg 143572b676d7Smrg int dstW = pOverlay->dstBox.x2 - pOverlay->dstBox.x1; 143672b676d7Smrg int dstH = pOverlay->dstBox.y2 - pOverlay->dstBox.y1; 143772b676d7Smrg int srcW = pOverlay->srcW; 143872b676d7Smrg int srcH = pOverlay->srcH; 143972b676d7Smrg CARD16 LCDheight = pSiS->LCDheight; 144072b676d7Smrg int srcPitch = pOverlay->origPitch; 144172b676d7Smrg int origdstH = dstH; 144272b676d7Smrg int modeflags = pOverlay->currentmode->Flags; 144372b676d7Smrg 144472b676d7Smrg /* Stretch image due to panel link scaling */ 144572b676d7Smrg if(pSiS->VBFlags & (CRT2_LCD | CRT1_LCDA)) { 144672b676d7Smrg if(pPriv->bridgeIsSlave) { 144772b676d7Smrg if(pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH)) { 144872b676d7Smrg if(pSiS->MiscFlags & MISC_PANELLINKSCALER) { 144972b676d7Smrg dstH = (dstH * LCDheight) / pOverlay->SCREENheight; 145072b676d7Smrg } 145172b676d7Smrg } 145272b676d7Smrg } else if((iscrt2 && (pSiS->VBFlags & CRT2_LCD)) || 145372b676d7Smrg (!iscrt2 && (pSiS->VBFlags & CRT1_LCDA))) { 145472b676d7Smrg if((pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH)) || (pSiS->VBFlags & CRT1_LCDA)) { 145572b676d7Smrg if(pSiS->MiscFlags & MISC_PANELLINKSCALER) { 145672b676d7Smrg dstH = (dstH * LCDheight) / pOverlay->SCREENheight; 145772b676d7Smrg if(pPriv->displayMode == DISPMODE_MIRROR) flag = 1; 145872b676d7Smrg } 145972b676d7Smrg } 146072b676d7Smrg } 146172b676d7Smrg if((pPriv->bridgeIsSlave || iscrt2) && 146272b676d7Smrg (pSiS->MiscFlags & MISC_STNMODE)) { 146372b676d7Smrg flag2 = 1; 146472b676d7Smrg } 146572b676d7Smrg } 146672b676d7Smrg 146772b676d7Smrg /* For double scan modes, we need to double the height 146872b676d7Smrg * On 315 and 550 (?), we need to double the width as well. 146972b676d7Smrg * Interlace mode vice versa. 147072b676d7Smrg */ 147172b676d7Smrg if((modeflags & V_DBLSCAN) && !flag2) { 147272b676d7Smrg dstH = origdstH << 1; 147372b676d7Smrg flag = 0; 147472b676d7Smrg if((pSiS->ChipType >= SIS_315H) && 147572b676d7Smrg (pSiS->ChipType <= SIS_550)) { 147672b676d7Smrg dstW <<= 1; 147772b676d7Smrg } 147872b676d7Smrg } else if(modeflags & V_INTERLACE) { 147972b676d7Smrg dstH = origdstH >> 1; 148072b676d7Smrg flag = 0; 148172b676d7Smrg } 148272b676d7Smrg 148372b676d7Smrg pOverlay->tap_scale = 1.0; 148472b676d7Smrg 148572b676d7Smrg if(dstW < OVERLAY_MIN_WIDTH) dstW = OVERLAY_MIN_WIDTH; 148672b676d7Smrg 148772b676d7Smrg if(dstW == srcW) { 148872b676d7Smrg 148972b676d7Smrg pOverlay->HUSF = 0x00; 149072b676d7Smrg pOverlay->IntBit = 0x05; 149172b676d7Smrg pOverlay->wHPre = 0; 149272b676d7Smrg 149372b676d7Smrg } else if(dstW > srcW) { 149472b676d7Smrg 149572b676d7Smrg pOverlay->IntBit = 0x04; 149672b676d7Smrg pOverlay->wHPre = 0; 149772b676d7Smrg 149872b676d7Smrg if(pPriv->havetapscaler) { 149972b676d7Smrg if((dstW > 2) && (srcW > 2)) { 150072b676d7Smrg pOverlay->HUSF = (((srcW - 2) << 16) + dstW - 3) / (dstW - 2); 150172b676d7Smrg } else { 150272b676d7Smrg pOverlay->HUSF = ((srcW << 16) + dstW - 1) / dstW; 150372b676d7Smrg } 150472b676d7Smrg } else { 150572b676d7Smrg dstW += 2; 150672b676d7Smrg pOverlay->HUSF = (srcW << 16) / dstW; 150772b676d7Smrg } 150872b676d7Smrg 150972b676d7Smrg } else { 151072b676d7Smrg 151172b676d7Smrg int tmpW = dstW; 151272b676d7Smrg 151372b676d7Smrg /* It seems, the hardware can't scale below factor .125 (=1/8) if the 151472b676d7Smrg pitch isn't a multiple of 256. 151572b676d7Smrg TODO: Test this on the 315 series! 151672b676d7Smrg */ 151772b676d7Smrg if((srcPitch % 256) || (srcPitch < 256)) { 151872b676d7Smrg if(((dstW * 1000) / srcW) < 125) dstW = tmpW = ((srcW * 125) / 1000) + 1; 151972b676d7Smrg } 152072b676d7Smrg 152172b676d7Smrg I = 0; 152272b676d7Smrg pOverlay->IntBit = 0x01; 152372b676d7Smrg while(srcW >= tmpW) { 152472b676d7Smrg tmpW <<= 1; 152572b676d7Smrg I++; 152672b676d7Smrg } 152772b676d7Smrg pOverlay->wHPre = (CARD8)(I - 1); 152872b676d7Smrg dstW <<= (I - 1); 152972b676d7Smrg 153072b676d7Smrg pOverlay->tap_scale = (float)srcW / (float)dstW; 153172b676d7Smrg if(pOverlay->tap_scale < 1.0) pOverlay->tap_scale = 1.0; 153272b676d7Smrg 153372b676d7Smrg if((srcW % dstW)) 153472b676d7Smrg pOverlay->HUSF = ((srcW - dstW) << 16) / dstW; 153572b676d7Smrg else 153672b676d7Smrg pOverlay->HUSF = 0; 153772b676d7Smrg } 153872b676d7Smrg 153972b676d7Smrg if(dstH < OVERLAY_MIN_HEIGHT) dstH = OVERLAY_MIN_HEIGHT; 154072b676d7Smrg 154172b676d7Smrg if(dstH == srcH) { 154272b676d7Smrg 154372b676d7Smrg pOverlay->VUSF = 0x00; 154472b676d7Smrg pOverlay->IntBit |= 0x0A; 154572b676d7Smrg 154672b676d7Smrg } else if(dstH > srcH) { 154772b676d7Smrg 154872b676d7Smrg dstH += 2; 154972b676d7Smrg pOverlay->IntBit |= 0x08; 155072b676d7Smrg 155172b676d7Smrg if(pPriv->havetapscaler) { 155272b676d7Smrg if((dstH > 2) && (srcH > 2)) { 155372b676d7Smrg pOverlay->VUSF = (((srcH - 2) << 16) - 32768 + dstH - 3) / (dstH - 2); 155472b676d7Smrg } else { 155572b676d7Smrg pOverlay->VUSF = ((srcH << 16) + dstH - 1) / dstH; 155672b676d7Smrg } 155772b676d7Smrg } else { 155872b676d7Smrg pOverlay->VUSF = (srcH << 16) / dstH; 155972b676d7Smrg } 156072b676d7Smrg 156172b676d7Smrg } else { 156272b676d7Smrg 156372b676d7Smrg I = srcH / dstH; 156472b676d7Smrg pOverlay->IntBit |= 0x02; 156572b676d7Smrg 156672b676d7Smrg if(I < 2) { 156772b676d7Smrg pOverlay->VUSF = ((srcH - dstH) << 16) / dstH; 156872b676d7Smrg /* Needed for LCD-scaling modes */ 156972b676d7Smrg if((flag) && (mult = (srcH / origdstH)) >= 2) { 157072b676d7Smrg pOverlay->pitch /= mult; 157172b676d7Smrg } 157272b676d7Smrg } else { 157372b676d7Smrg#if 0 157472b676d7Smrg if(((pOverlay->bobEnable & 0x08) == 0x00) && 157572b676d7Smrg (((srcPitch * I) >> 2) > 0xFFF)){ 157672b676d7Smrg pOverlay->bobEnable |= 0x08; 157772b676d7Smrg srcPitch >>= 1; 157872b676d7Smrg } 157972b676d7Smrg#endif 158072b676d7Smrg if(((srcPitch * I) >> 2) > 0xFFF) { 158172b676d7Smrg I = (0xFFF * 2 / srcPitch); 158272b676d7Smrg pOverlay->VUSF = 0xFFFF; 158372b676d7Smrg } else { 158472b676d7Smrg dstH = I * dstH; 158572b676d7Smrg if(srcH % dstH) 158672b676d7Smrg pOverlay->VUSF = ((srcH - dstH) << 16) / dstH; 158772b676d7Smrg else 158872b676d7Smrg pOverlay->VUSF = 0; 158972b676d7Smrg } 159072b676d7Smrg /* set video frame buffer offset */ 159172b676d7Smrg pOverlay->pitch = (CARD16)(srcPitch * I); 159272b676d7Smrg } 159372b676d7Smrg } 159472b676d7Smrg} 159572b676d7Smrg 159672b676d7Smrg#ifdef SISMERGED 159772b676d7Smrgstatic void 159872b676d7Smrgcalc_scale_factor_2(SISOverlayPtr pOverlay, ScrnInfoPtr pScrn, 159972b676d7Smrg SISPortPrivPtr pPriv, int index, int iscrt2) 160072b676d7Smrg{ 160172b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 160272b676d7Smrg CARD32 I=0,mult=0; 160372b676d7Smrg int flag=0, flag2=0; 160472b676d7Smrg 160572b676d7Smrg int dstW = pOverlay->dstBox2.x2 - pOverlay->dstBox2.x1; 160672b676d7Smrg int dstH = pOverlay->dstBox2.y2 - pOverlay->dstBox2.y1; 160772b676d7Smrg int srcW = pOverlay->srcW2; 160872b676d7Smrg int srcH = pOverlay->srcH2; 160972b676d7Smrg CARD16 LCDheight = pSiS->LCDheight; 161072b676d7Smrg int srcPitch = pOverlay->origPitch; 161172b676d7Smrg int origdstH = dstH; 161272b676d7Smrg int modeflags = pOverlay->currentmode2->Flags; 161372b676d7Smrg 161472b676d7Smrg /* Stretch image due to panel link scaling */ 161572b676d7Smrg if(pSiS->VBFlags & CRT2_LCD) { 161672b676d7Smrg if(pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH)) { 161772b676d7Smrg if(pSiS->MiscFlags & MISC_PANELLINKSCALER) { 161872b676d7Smrg dstH = (dstH * LCDheight) / pOverlay->SCREENheight2; 161972b676d7Smrg flag = 1; 162072b676d7Smrg } 162172b676d7Smrg if(pSiS->MiscFlags & MISC_STNMODE) flag2 = 1; 162272b676d7Smrg } 162372b676d7Smrg } 162472b676d7Smrg /* For double scan modes, we need to double the height 162572b676d7Smrg * On 315 and 550 (?), we need to double the width as well. 162672b676d7Smrg * Interlace mode vice versa. 162772b676d7Smrg */ 162872b676d7Smrg if((modeflags & V_DBLSCAN) && !flag2) { 162972b676d7Smrg dstH = origdstH << 1; 163072b676d7Smrg flag = 0; 163172b676d7Smrg if((pSiS->ChipType >= SIS_315H) && 163272b676d7Smrg (pSiS->ChipType <= SIS_550)) { 163372b676d7Smrg dstW <<= 1; 163472b676d7Smrg } 163572b676d7Smrg } 163672b676d7Smrg if(modeflags & V_INTERLACE) { 163772b676d7Smrg dstH = origdstH >> 1; 163872b676d7Smrg flag = 0; 163972b676d7Smrg } 164072b676d7Smrg 164172b676d7Smrg pOverlay->tap_scale2 = 1.0; 164272b676d7Smrg 164372b676d7Smrg if(dstW < OVERLAY_MIN_WIDTH) dstW = OVERLAY_MIN_WIDTH; 164472b676d7Smrg 164572b676d7Smrg if(dstW == srcW) { 164672b676d7Smrg 164772b676d7Smrg pOverlay->HUSF2 = 0x00; 164872b676d7Smrg pOverlay->IntBit2 = 0x05; 164972b676d7Smrg pOverlay->wHPre2 = 0; 165072b676d7Smrg 165172b676d7Smrg } else if(dstW > srcW) { 165272b676d7Smrg 165372b676d7Smrg pOverlay->IntBit2 = 0x04; 165472b676d7Smrg pOverlay->wHPre2 = 0; 165572b676d7Smrg 165672b676d7Smrg if(pPriv->havetapscaler) { 165772b676d7Smrg if((dstW > 2) && (srcW > 2)) { 165872b676d7Smrg pOverlay->HUSF2 = (((srcW - 2) << 16) + dstW - 3) / (dstW - 2); 165972b676d7Smrg } else { 166072b676d7Smrg pOverlay->HUSF2 = ((srcW << 16) + dstW - 1) / dstW; 166172b676d7Smrg } 166272b676d7Smrg } else { 166372b676d7Smrg dstW += 2; 166472b676d7Smrg pOverlay->HUSF2 = (srcW << 16) / dstW; 166572b676d7Smrg } 166672b676d7Smrg 166772b676d7Smrg } else { 166872b676d7Smrg 166972b676d7Smrg int tmpW = dstW; 167072b676d7Smrg 167172b676d7Smrg /* It seems, the hardware can't scale below factor .125 (=1/8) if the 167272b676d7Smrg pitch isn't a multiple of 256. 167372b676d7Smrg TODO: Test this on the 315 series! 167472b676d7Smrg */ 167572b676d7Smrg if((srcPitch % 256) || (srcPitch < 256)) { 167672b676d7Smrg if(((dstW * 1000) / srcW) < 125) dstW = tmpW = ((srcW * 125) / 1000) + 1; 167772b676d7Smrg } 167872b676d7Smrg 167972b676d7Smrg I = 0; 168072b676d7Smrg pOverlay->IntBit2 = 0x01; 168172b676d7Smrg while(srcW >= tmpW) { 168272b676d7Smrg tmpW <<= 1; 168372b676d7Smrg I++; 168472b676d7Smrg } 168572b676d7Smrg pOverlay->wHPre2 = (CARD8)(I - 1); 168672b676d7Smrg dstW <<= (I - 1); 168772b676d7Smrg 168872b676d7Smrg pOverlay->tap_scale2 = (float)srcW / (float)dstW; 168972b676d7Smrg if(pOverlay->tap_scale2 < 1.0) pOverlay->tap_scale2 = 1.0; 169072b676d7Smrg 169172b676d7Smrg if((srcW % dstW)) 169272b676d7Smrg pOverlay->HUSF2 = ((srcW - dstW) << 16) / dstW; 169372b676d7Smrg else 169472b676d7Smrg pOverlay->HUSF2 = 0x00; 169572b676d7Smrg } 169672b676d7Smrg 169772b676d7Smrg if(dstH < OVERLAY_MIN_HEIGHT) dstH = OVERLAY_MIN_HEIGHT; 169872b676d7Smrg 169972b676d7Smrg if(dstH == srcH) { 170072b676d7Smrg 170172b676d7Smrg pOverlay->VUSF2 = 0x00; 170272b676d7Smrg pOverlay->IntBit2 |= 0x0A; 170372b676d7Smrg 170472b676d7Smrg } else if(dstH > srcH) { 170572b676d7Smrg 170672b676d7Smrg dstH += 2; 170772b676d7Smrg pOverlay->IntBit2 |= 0x08; 170872b676d7Smrg 170972b676d7Smrg if(pPriv->havetapscaler) { 171072b676d7Smrg if((dstH > 2) && (srcH > 2)) { 171172b676d7Smrg pOverlay->VUSF2 = (((srcH - 2) << 16) - 32768 + dstH - 3) / (dstH - 2); 171272b676d7Smrg } else { 171372b676d7Smrg pOverlay->VUSF2 = ((srcH << 16) + dstH - 1) / dstH; 171472b676d7Smrg } 171572b676d7Smrg } else { 171672b676d7Smrg pOverlay->VUSF2 = (srcH << 16) / dstH; 171772b676d7Smrg } 171872b676d7Smrg 171972b676d7Smrg } else { 172072b676d7Smrg 172172b676d7Smrg I = srcH / dstH; 172272b676d7Smrg pOverlay->IntBit2 |= 0x02; 172372b676d7Smrg 172472b676d7Smrg if(I < 2) { 172572b676d7Smrg pOverlay->VUSF2 = ((srcH - dstH) << 16) / dstH; 172672b676d7Smrg /* Needed for LCD-scaling modes */ 172772b676d7Smrg if(flag && ((mult = (srcH / origdstH)) >= 2)) { 172872b676d7Smrg pOverlay->pitch2 /= mult; 172972b676d7Smrg } 173072b676d7Smrg } else { 173172b676d7Smrg#if 0 173272b676d7Smrg if(((pOverlay->bobEnable & 0x08) == 0x00) && 173372b676d7Smrg (((srcPitch * I)>>2) > 0xFFF)){ 173472b676d7Smrg pOverlay->bobEnable |= 0x08; 173572b676d7Smrg srcPitch >>= 1; 173672b676d7Smrg } 173772b676d7Smrg#endif 173872b676d7Smrg if(((srcPitch * I) >> 2) > 0xFFF) { 173972b676d7Smrg I = (0xFFF * 2 / srcPitch); 174072b676d7Smrg pOverlay->VUSF2 = 0xFFFF; 174172b676d7Smrg } else { 174272b676d7Smrg dstH = I * dstH; 174372b676d7Smrg if(srcH % dstH) 174472b676d7Smrg pOverlay->VUSF2 = ((srcH - dstH) << 16) / dstH; 174572b676d7Smrg else 174672b676d7Smrg pOverlay->VUSF2 = 0x00; 174772b676d7Smrg } 174872b676d7Smrg /* set video frame buffer offset */ 174972b676d7Smrg pOverlay->pitch2 = (CARD16)(srcPitch * I); 175072b676d7Smrg } 175172b676d7Smrg } 175272b676d7Smrg} 175372b676d7Smrg#endif 175472b676d7Smrg 175572b676d7Smrg/********************************* 175672b676d7Smrg * Handle 4-tap scaler (340) * 175772b676d7Smrg *********************************/ 175872b676d7Smrg 175972b676d7Smrgstatic float 176072b676d7Smrgtap_dda_func(float x) 176172b676d7Smrg{ 176272b676d7Smrg double pi = 3.14159265358979; 176372b676d7Smrg float r = 0.5, y; 176472b676d7Smrg 176572b676d7Smrg if(x == 0.0) { 176672b676d7Smrg y = 1.0; 176772b676d7Smrg } else if(x == -1.0 || x == 1.0) { 176872b676d7Smrg y = 0.0; 176972b676d7Smrg /* case ((x == -1.0 / (r * 2.0)) || (x == 1.0 / (r * 2.0))): */ 177072b676d7Smrg /* y = (float)(r / 2.0 * sin(pi / (2.0 * r))); = 0.013700916287197; */ 177172b676d7Smrg } else { 177272b676d7Smrg y = sin(pi * x) / (pi * x) * cos(r * pi * x) / (1 - x * x); 177372b676d7Smrg /* y = sin(pi * x) / (pi * x) * cos(r * pi * x) / (1 - 4 * r * r * x * x); */ 177472b676d7Smrg } 177572b676d7Smrg 177672b676d7Smrg return y; 177772b676d7Smrg} 177872b676d7Smrg 177972b676d7Smrgstatic void 178072b676d7Smrgset_dda_regs(SISPtr pSiS, float scale) 178172b676d7Smrg{ 178272b676d7Smrg float W[4], WS, myadd; 178372b676d7Smrg int *temp[4], *wm1, *wm2, *wm3, *wm4; 178472b676d7Smrg int i, j, w, tidx, weightmatrix[16][4]; 178572b676d7Smrg 178672b676d7Smrg for(i = 0; i < 16; i++) { 178772b676d7Smrg 178872b676d7Smrg myadd = ((float)i) / 16.0; 178972b676d7Smrg WS = W[0] = tap_dda_func((myadd + 1.0) / scale); 179072b676d7Smrg W[1] = tap_dda_func(myadd / scale); 179172b676d7Smrg WS += W[1]; 179272b676d7Smrg W[2] = tap_dda_func((myadd - 1.0) / scale); 179372b676d7Smrg WS += W[2]; 179472b676d7Smrg W[3] = tap_dda_func((myadd - 2.0) / scale); 179572b676d7Smrg WS += W[3]; 179672b676d7Smrg 179772b676d7Smrg w = 0; 179872b676d7Smrg for(j = 0; j < 4; j++) { 179972b676d7Smrg weightmatrix[i][j] = (int)(((float)((W[j] * 16.0 / WS) + 0.5))); 180072b676d7Smrg w += weightmatrix[i][j]; 180172b676d7Smrg } 180272b676d7Smrg 180372b676d7Smrg if(w == 12) { 180472b676d7Smrg 180572b676d7Smrg weightmatrix[i][0]++; 180672b676d7Smrg weightmatrix[i][1]++; 180772b676d7Smrg weightmatrix[i][2]++; 180872b676d7Smrg weightmatrix[i][3]++; 180972b676d7Smrg 181072b676d7Smrg } else if(w == 20) { 181172b676d7Smrg 181272b676d7Smrg weightmatrix[i][0]--; 181372b676d7Smrg weightmatrix[i][1]--; 181472b676d7Smrg weightmatrix[i][2]--; 181572b676d7Smrg weightmatrix[i][3]--; 181672b676d7Smrg 181772b676d7Smrg } else if(w != 16) { 181872b676d7Smrg 181972b676d7Smrg tidx = (weightmatrix[i][0] > weightmatrix[i][1]) ? 0 : 1; 182072b676d7Smrg temp[0] = &weightmatrix[i][tidx]; 182172b676d7Smrg temp[1] = &weightmatrix[i][tidx ^ 1]; 182272b676d7Smrg 182372b676d7Smrg tidx = (weightmatrix[i][2] > weightmatrix[i][3]) ? 2 : 3; 182472b676d7Smrg temp[2] = &weightmatrix[i][tidx]; 182572b676d7Smrg temp[3] = &weightmatrix[i][tidx ^ 1]; 182672b676d7Smrg 182772b676d7Smrg tidx = (*(temp[0]) > *(temp[2])) ? 0 : 2; 182872b676d7Smrg wm1 = temp[tidx]; 182972b676d7Smrg wm2 = temp[tidx ^ 2]; 183072b676d7Smrg 183172b676d7Smrg tidx = (*(temp[1]) > *(temp[3])) ? 1 : 3; 183272b676d7Smrg wm3 = temp[tidx]; 183372b676d7Smrg wm4 = temp[tidx ^ 2]; 183472b676d7Smrg 183572b676d7Smrg switch(w) { 183672b676d7Smrg case 13: 183772b676d7Smrg (*wm1)++; 183872b676d7Smrg (*wm4)++; 183972b676d7Smrg if(*wm2 > *wm3) (*wm2)++; 184072b676d7Smrg else (*wm3)++; 184172b676d7Smrg break; 184272b676d7Smrg case 14: 184372b676d7Smrg (*wm1)++; 184472b676d7Smrg (*wm4)++; 184572b676d7Smrg break; 184672b676d7Smrg case 15: 184772b676d7Smrg (*wm1)++; 184872b676d7Smrg break; 184972b676d7Smrg case 17: 185072b676d7Smrg (*wm4)--; 185172b676d7Smrg break; 185272b676d7Smrg case 18: 185372b676d7Smrg (*wm1)--; 185472b676d7Smrg (*wm4)--; 185572b676d7Smrg break; 185672b676d7Smrg case 19: 185772b676d7Smrg (*wm1)--; 185872b676d7Smrg (*wm4)--; 185972b676d7Smrg if(*wm2 > *wm3) (*wm3)--; 186072b676d7Smrg else (*wm2)--; 186172b676d7Smrg } 186272b676d7Smrg } 186372b676d7Smrg } 186472b676d7Smrg 186572b676d7Smrg /* Set 4-tap scaler video regs 0x75-0xb4 */ 186672b676d7Smrg w = 0x75; 186772b676d7Smrg for(i = 0; i < 16; i++) { 186872b676d7Smrg for(j = 0; j < 4; j++, w++) { 186972b676d7Smrg setvideoregmask(pSiS, w, weightmatrix[i][j], 0x3f); 187072b676d7Smrg } 187172b676d7Smrg } 187272b676d7Smrg} 187372b676d7Smrg 187472b676d7Smrg/********************************* 187572b676d7Smrg * Calc line buffer size * 187672b676d7Smrg *********************************/ 187772b676d7Smrg 187872b676d7Smrgstatic CARD16 187972b676d7Smrgcalc_line_buf_size(CARD32 srcW, CARD8 wHPre, CARD8 planar, SISPortPrivPtr pPriv) 188072b676d7Smrg{ 188172b676d7Smrg CARD32 I, mask = 0xffffffff, shift = pPriv->is761 ? 1 : 0; 188272b676d7Smrg 188372b676d7Smrg if(planar) { 188472b676d7Smrg 188572b676d7Smrg switch(wHPre & 0x07) { 188672b676d7Smrg case 3: 188772b676d7Smrg shift += 8; 188872b676d7Smrg mask <<= shift; 188972b676d7Smrg I = srcW >> shift; 189072b676d7Smrg if((mask & srcW) != srcW) I++; 189172b676d7Smrg I <<= 5; 189272b676d7Smrg break; 189372b676d7Smrg case 4: 189472b676d7Smrg shift += 9; 189572b676d7Smrg mask <<= shift; 189672b676d7Smrg I = srcW >> shift; 189772b676d7Smrg if((mask & srcW) != srcW) I++; 189872b676d7Smrg I <<= 6; 189972b676d7Smrg break; 190072b676d7Smrg case 5: 190172b676d7Smrg shift += 10; 190272b676d7Smrg mask <<= shift; 190372b676d7Smrg I = srcW >> shift; 190472b676d7Smrg if((mask & srcW) != srcW) I++; 190572b676d7Smrg I <<= 7; 190672b676d7Smrg break; 190772b676d7Smrg case 6: 190872b676d7Smrg if(pPriv->is340 || pPriv->isXGI || pPriv->is761) { 190972b676d7Smrg shift += 11; 191072b676d7Smrg mask <<= shift; 191172b676d7Smrg I = srcW >> shift; 191272b676d7Smrg if((mask & srcW) != srcW) I++; 191372b676d7Smrg I <<= 8; 191472b676d7Smrg break; 191572b676d7Smrg } else { 191672b676d7Smrg return((CARD16)(255)); 191772b676d7Smrg } 191872b676d7Smrg default: 191972b676d7Smrg shift += 7; 192072b676d7Smrg mask <<= shift; 192172b676d7Smrg I = srcW >> shift; 192272b676d7Smrg if((mask & srcW) != srcW) I++; 192372b676d7Smrg I <<= 4; 192472b676d7Smrg break; 192572b676d7Smrg } 192672b676d7Smrg 192772b676d7Smrg } else { /* packed */ 192872b676d7Smrg 192972b676d7Smrg shift += 3; 193072b676d7Smrg mask <<= shift; 193172b676d7Smrg I = srcW >> shift; 193272b676d7Smrg if((mask & srcW) != srcW) I++; 193372b676d7Smrg 193472b676d7Smrg } 193572b676d7Smrg 193672b676d7Smrg if(I <= 3) I = 4; 193772b676d7Smrg 193872b676d7Smrg return((CARD16)(I - 1)); 193972b676d7Smrg} 194072b676d7Smrg 194172b676d7Smrgstatic __inline void 194272b676d7Smrgcalc_line_buf_size_1(SISOverlayPtr pOverlay, SISPortPrivPtr pPriv) 194372b676d7Smrg{ 194472b676d7Smrg pOverlay->lineBufSize = 194572b676d7Smrg calc_line_buf_size(pOverlay->srcW, pOverlay->wHPre, pOverlay->planar, pPriv); 194672b676d7Smrg} 194772b676d7Smrg 194872b676d7Smrg#ifdef SISMERGED 194972b676d7Smrgstatic __inline void 195072b676d7Smrgcalc_line_buf_size_2(SISOverlayPtr pOverlay, SISPortPrivPtr pPriv) 195172b676d7Smrg{ 195272b676d7Smrg pOverlay->lineBufSize2 = 195372b676d7Smrg calc_line_buf_size(pOverlay->srcW2, pOverlay->wHPre2, pOverlay->planar, pPriv); 195472b676d7Smrg} 195572b676d7Smrg 195672b676d7Smrg/********************************** 195772b676d7Smrg *En/Disable merging of linebuffer* 195872b676d7Smrg **********************************/ 195972b676d7Smrg 196072b676d7Smrgstatic void 196172b676d7Smrgmerge_line_buf_mfb(SISPtr pSiS, SISPortPrivPtr pPriv, Bool enable1, Bool enable2, 196272b676d7Smrg short width1, short width2, short limit) 196372b676d7Smrg{ 196472b676d7Smrg UChar misc1, misc2, mask = pPriv->linebufmask; 196572b676d7Smrg 196672b676d7Smrg if(pPriv->hasTwoOverlays) { /* This means we are in MIRROR mode */ 196772b676d7Smrg 196872b676d7Smrg misc2 = 0x00; 196972b676d7Smrg if(enable1) misc1 = 0x04; 197072b676d7Smrg else misc1 = 0x00; 197172b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc2, misc2, mask); 197272b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc1, misc1, 0x04); 197372b676d7Smrg 197472b676d7Smrg misc2 = 0x01; 197572b676d7Smrg if(enable2) misc1 = 0x04; 197672b676d7Smrg else misc1 = 0x00; 197772b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc2, misc2, mask); 197872b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc1, misc1, 0x04); 197972b676d7Smrg 198072b676d7Smrg } else { /* This means we are either in SINGLE1 or SINGLE2 mode */ 198172b676d7Smrg 198272b676d7Smrg misc2 = 0x00; 198372b676d7Smrg if(enable1 || enable2) { 198472b676d7Smrg if(pSiS->MiscFlags & MISC_SIS760ONEOVERLAY) { 198572b676d7Smrg if((width1 > (limit * 2)) || (width2 > (limit * 2))) { 198672b676d7Smrg misc2 = 0x20; 198772b676d7Smrg } else { 198872b676d7Smrg misc2 = 0x10; 198972b676d7Smrg } 199072b676d7Smrg misc1 = 0x00; 199172b676d7Smrg } else { 199272b676d7Smrg misc1 = 0x04; 199372b676d7Smrg } 199472b676d7Smrg } else { 199572b676d7Smrg misc1 = 0x00; 199672b676d7Smrg } 199772b676d7Smrg 199872b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc2, misc2, mask); 199972b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc1, misc1, 0x04); 200072b676d7Smrg 200172b676d7Smrg } 200272b676d7Smrg} 200372b676d7Smrg#endif 200472b676d7Smrg 200572b676d7Smrg/* About linebuffer merging: 200672b676d7Smrg * 200772b676d7Smrg * For example the 651: 200872b676d7Smrg * Each overlay has 4 line buffers, 384 bytes each (<-- Is that really correct? 1920 / 384 = 5 !!!) 200972b676d7Smrg * If the source width is greater than 384, line buffers must be merged. 201072b676d7Smrg * Dual merge: Only O1 usable (uses overlay 2's linebuffer), maximum width 384*2 201172b676d7Smrg * Individual merge: Both overlays available, maximum width 384*2 201272b676d7Smrg * All merge: Only overlay 1 available, maximum width = 384*4 (<--- should be 1920, is 1536...) 201372b676d7Smrg * 201472b676d7Smrg * 201572b676d7Smrg * Normally: Dual merge: Individual merge 201672b676d7Smrg * Overlay 1 Overlay 2 Overlay 1 only! Both overlays 201772b676d7Smrg * ___1___ ___5___ ___1___ ___2___ -\ O1 ___1___ ___2___ 201872b676d7Smrg * ___2___ ___6___ ___3___ ___4___ \_ O 1 O1 ___3___ ___4___ 201972b676d7Smrg * ___3___ ___7___ ___5___ ___6___ / O2 ___5___ ___6___ 202072b676d7Smrg * ___4___ ___8___ ___7___ ___8___ -/ O2 ___7___ ___8___ 202172b676d7Smrg * 202272b676d7Smrg * 202372b676d7Smrg * All merge: ___1___ ___2___ ___3___ ___4___ 202472b676d7Smrg * (Overlay 1 only!) ___5___ ___6___ ___7___ ___8___ 202572b676d7Smrg * 202672b676d7Smrg * Individual merge is supported on all chipsets. 202772b676d7Smrg * Dual merge is only supported on the 300 series and M650/651 and later. 202872b676d7Smrg * All merge is only supported on the M650/651 and later. 202972b676d7Smrg * Single-Overlay-chipsets only support Individual merge. 203072b676d7Smrg * 203172b676d7Smrg */ 203272b676d7Smrg 203372b676d7Smrgstatic void 203472b676d7Smrgmerge_line_buf(SISPtr pSiS, SISPortPrivPtr pPriv, Bool enable, short width, short limit) 203572b676d7Smrg{ 203672b676d7Smrg UChar misc1, misc2, mask = pPriv->linebufmask; 203772b676d7Smrg 203872b676d7Smrg if(enable) { /* ----- enable linebuffer merge */ 203972b676d7Smrg 204072b676d7Smrg switch(pPriv->displayMode){ 204172b676d7Smrg case DISPMODE_SINGLE1: 204272b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA) { 204372b676d7Smrg if(pPriv->dualHeadMode) { 204472b676d7Smrg misc2 = 0x00; 204572b676d7Smrg misc1 = 0x04; 204672b676d7Smrg } else { 204772b676d7Smrg misc2 = 0x10; 204872b676d7Smrg misc1 = 0x00; 204972b676d7Smrg } 205072b676d7Smrg } else { 205172b676d7Smrg if(pPriv->hasTwoOverlays) { 205272b676d7Smrg if(pPriv->dualHeadMode) { 205372b676d7Smrg misc2 = 0x00; 205472b676d7Smrg misc1 = 0x04; 205572b676d7Smrg } else { 205672b676d7Smrg if(width > (limit * 2)) { 205772b676d7Smrg misc2 = 0x20; 205872b676d7Smrg } else { 205972b676d7Smrg misc2 = 0x10; 206072b676d7Smrg } 206172b676d7Smrg misc1 = 0x00; 206272b676d7Smrg } 206372b676d7Smrg } else if(pSiS->MiscFlags & MISC_SIS760ONEOVERLAY) { 206472b676d7Smrg if(width > (limit * 2)) { 206572b676d7Smrg misc2 = 0x20; 206672b676d7Smrg } else { 206772b676d7Smrg misc2 = 0x10; 206872b676d7Smrg } 206972b676d7Smrg misc1 = 0x00; 207072b676d7Smrg } else { 207172b676d7Smrg misc2 = 0x00; 207272b676d7Smrg misc1 = 0x04; 207372b676d7Smrg } 207472b676d7Smrg } 207572b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc2, misc2, mask); 207672b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc1, misc1, 0x04); 207772b676d7Smrg break; 207872b676d7Smrg 207972b676d7Smrg case DISPMODE_SINGLE2: 208072b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA) { 208172b676d7Smrg if(pPriv->dualHeadMode) { 208272b676d7Smrg misc2 = 0x01; 208372b676d7Smrg misc1 = 0x04; 208472b676d7Smrg } else { 208572b676d7Smrg misc2 = 0x10; 208672b676d7Smrg misc1 = 0x00; 208772b676d7Smrg } 208872b676d7Smrg } else { 208972b676d7Smrg if(pPriv->hasTwoOverlays) { 209072b676d7Smrg if(pPriv->dualHeadMode) { 209172b676d7Smrg misc2 = 0x01; 209272b676d7Smrg misc1 = 0x04; 209372b676d7Smrg } else { 209472b676d7Smrg if(width > (limit * 2)) { 209572b676d7Smrg misc2 = 0x20; 209672b676d7Smrg } else { 209772b676d7Smrg misc2 = 0x10; 209872b676d7Smrg } 209972b676d7Smrg misc1 = 0x00; 210072b676d7Smrg } 210172b676d7Smrg } else if(pSiS->MiscFlags & MISC_SIS760ONEOVERLAY) { 210272b676d7Smrg if(width > (limit * 2)) { 210372b676d7Smrg misc2 = 0x20; 210472b676d7Smrg } else { 210572b676d7Smrg misc2 = 0x10; 210672b676d7Smrg } 210772b676d7Smrg misc1 = 0x00; 210872b676d7Smrg } else { 210972b676d7Smrg misc2 = 0x00; 211072b676d7Smrg misc1 = 0x04; 211172b676d7Smrg } 211272b676d7Smrg } 211372b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc2, misc2, mask); 211472b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc1, misc1, 0x04); 211572b676d7Smrg break; 211672b676d7Smrg 211772b676d7Smrg case DISPMODE_MIRROR: /* This can only be on chips with 2 overlays */ 211872b676d7Smrg default: 211972b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, mask); 212072b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x04, 0x04); 212172b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, mask); 212272b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x04, 0x04); 212372b676d7Smrg break; 212472b676d7Smrg } 212572b676d7Smrg 212672b676d7Smrg } else { /* ----- disable linebuffer merge */ 212772b676d7Smrg 212872b676d7Smrg switch(pPriv->displayMode) { 212972b676d7Smrg 213072b676d7Smrg case DISPMODE_SINGLE1: 213172b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, mask); 213272b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x04); 213372b676d7Smrg break; 213472b676d7Smrg 213572b676d7Smrg case DISPMODE_SINGLE2: 213672b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA) { 213772b676d7Smrg if(pPriv->dualHeadMode) misc2 = 0x01; 213872b676d7Smrg else misc2 = 0x00; 213972b676d7Smrg } else { 214072b676d7Smrg if(pPriv->hasTwoOverlays) { 214172b676d7Smrg if(pPriv->dualHeadMode) misc2 = 0x01; 214272b676d7Smrg else misc2 = 0x00; 214372b676d7Smrg } else { 214472b676d7Smrg misc2 = 0x00; 214572b676d7Smrg } 214672b676d7Smrg } 214772b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc2, misc2, mask); 214872b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x04); 214972b676d7Smrg break; 215072b676d7Smrg 215172b676d7Smrg case DISPMODE_MIRROR: /* This can only be on chips with 2 overlays */ 215272b676d7Smrg default: 215372b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, mask); 215472b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x04); 215572b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, mask); 215672b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x04); 215772b676d7Smrg break; 215872b676d7Smrg } 215972b676d7Smrg } 216072b676d7Smrg} 216172b676d7Smrg 216272b676d7Smrg/********************************* 216372b676d7Smrg * Select video format * 216472b676d7Smrg *********************************/ 216572b676d7Smrg 216672b676d7Smrgstatic __inline void 216772b676d7Smrgset_format(SISPtr pSiS, SISOverlayPtr pOverlay) 216872b676d7Smrg{ 216972b676d7Smrg CARD8 fmt; 217072b676d7Smrg 217172b676d7Smrg switch (pOverlay->pixelFormat){ 217272b676d7Smrg case PIXEL_FMT_YV12: 217372b676d7Smrg case PIXEL_FMT_I420: 217472b676d7Smrg fmt = 0x0c; 217572b676d7Smrg break; 217672b676d7Smrg case PIXEL_FMT_YUY2: 217772b676d7Smrg fmt = 0x28; 217872b676d7Smrg break; 217972b676d7Smrg case PIXEL_FMT_UYVY: 218072b676d7Smrg fmt = 0x08; 218172b676d7Smrg break; 218272b676d7Smrg case PIXEL_FMT_YVYU: 218372b676d7Smrg fmt = 0x38; 218472b676d7Smrg break; 218572b676d7Smrg case PIXEL_FMT_NV12: 218672b676d7Smrg fmt = 0x4c; 218772b676d7Smrg break; 218872b676d7Smrg case PIXEL_FMT_NV21: 218972b676d7Smrg fmt = 0x5c; 219072b676d7Smrg break; 219172b676d7Smrg case PIXEL_FMT_RGB5: /* D[5:4] : 00 RGB555, 01 RGB 565 */ 219272b676d7Smrg fmt = 0x00; 219372b676d7Smrg break; 219472b676d7Smrg case PIXEL_FMT_RGB6: 219572b676d7Smrg fmt = 0x10; 219672b676d7Smrg break; 219772b676d7Smrg default: 219872b676d7Smrg fmt = 0x00; 219972b676d7Smrg } 220072b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc0, fmt, 0xfc); 220172b676d7Smrg} 220272b676d7Smrg 220372b676d7Smrg/********************************* 220472b676d7Smrg * Set various video registers * 220572b676d7Smrg *********************************/ 220672b676d7Smrg 220772b676d7Smrgstatic __inline void 220872b676d7Smrgset_colorkey(SISPtr pSiS, CARD32 colorkey) 220972b676d7Smrg{ 221072b676d7Smrg CARD8 r, g, b; 221172b676d7Smrg 221272b676d7Smrg b = (CARD8)(colorkey & 0xFF); 221372b676d7Smrg g = (CARD8)((colorkey >> 8) & 0xFF); 221472b676d7Smrg r = (CARD8)((colorkey >> 16) & 0xFF); 221572b676d7Smrg 221672b676d7Smrg setvideoreg(pSiS, Index_VI_Overlay_ColorKey_Blue_Min ,(CARD8)b); 221772b676d7Smrg setvideoreg(pSiS, Index_VI_Overlay_ColorKey_Green_Min ,(CARD8)g); 221872b676d7Smrg setvideoreg(pSiS, Index_VI_Overlay_ColorKey_Red_Min ,(CARD8)r); 221972b676d7Smrg 222072b676d7Smrg setvideoreg(pSiS, Index_VI_Overlay_ColorKey_Blue_Max ,(CARD8)b); 222172b676d7Smrg setvideoreg(pSiS, Index_VI_Overlay_ColorKey_Green_Max ,(CARD8)g); 222272b676d7Smrg setvideoreg(pSiS, Index_VI_Overlay_ColorKey_Red_Max ,(CARD8)r); 222372b676d7Smrg} 222472b676d7Smrg 222572b676d7Smrgstatic __inline void 222672b676d7Smrgset_chromakey(SISPtr pSiS, CARD32 chromamin, CARD32 chromamax) 222772b676d7Smrg{ 222872b676d7Smrg CARD8 r1, g1, b1; 222972b676d7Smrg CARD8 r2, g2, b2; 223072b676d7Smrg 223172b676d7Smrg b1 = (CARD8)(chromamin & 0xFF); 223272b676d7Smrg g1 = (CARD8)((chromamin >> 8) & 0xFF); 223372b676d7Smrg r1 = (CARD8)((chromamin >> 16) & 0xFF); 223472b676d7Smrg b2 = (CARD8)(chromamax & 0xFF); 223572b676d7Smrg g2 = (CARD8)((chromamax >> 8) & 0xFF); 223672b676d7Smrg r2 = (CARD8)((chromamax >> 16) & 0xFF); 223772b676d7Smrg 223872b676d7Smrg setvideoreg(pSiS, Index_VI_Overlay_ChromaKey_Blue_V_Min ,(CARD8)b1); 223972b676d7Smrg setvideoreg(pSiS, Index_VI_Overlay_ChromaKey_Green_U_Min ,(CARD8)g1); 224072b676d7Smrg setvideoreg(pSiS, Index_VI_Overlay_ChromaKey_Red_Y_Min ,(CARD8)r1); 224172b676d7Smrg 224272b676d7Smrg setvideoreg(pSiS, Index_VI_Overlay_ChromaKey_Blue_V_Max ,(CARD8)b2); 224372b676d7Smrg setvideoreg(pSiS, Index_VI_Overlay_ChromaKey_Green_U_Max ,(CARD8)g2); 224472b676d7Smrg setvideoreg(pSiS, Index_VI_Overlay_ChromaKey_Red_Y_Max ,(CARD8)r2); 224572b676d7Smrg} 224672b676d7Smrg 224772b676d7Smrgstatic __inline void 224872b676d7Smrgset_brightness(SISPtr pSiS, CARD8 brightness) 224972b676d7Smrg{ 225072b676d7Smrg setvideoreg(pSiS, Index_VI_Brightness, brightness); 225172b676d7Smrg} 225272b676d7Smrg 225372b676d7Smrgstatic __inline void 225472b676d7Smrgset_contrast(SISPtr pSiS, CARD8 contrast) 225572b676d7Smrg{ 225672b676d7Smrg setvideoregmask(pSiS, Index_VI_Contrast_Enh_Ctrl, contrast, 0x07); 225772b676d7Smrg} 225872b676d7Smrg 225972b676d7Smrg/* 315 series and later only */ 226072b676d7Smrgstatic __inline void 226172b676d7Smrgset_saturation(SISPtr pSiS, short saturation) 226272b676d7Smrg{ 226372b676d7Smrg CARD8 temp = 0; 226472b676d7Smrg 226572b676d7Smrg if(saturation < 0) { 226672b676d7Smrg temp |= 0x88; 226772b676d7Smrg saturation = -saturation; 226872b676d7Smrg } 226972b676d7Smrg temp |= (saturation & 0x07); 227072b676d7Smrg temp |= ((saturation & 0x07) << 4); 227172b676d7Smrg 227272b676d7Smrg setvideoreg(pSiS, Index_VI_Saturation, temp); 227372b676d7Smrg} 227472b676d7Smrg 227572b676d7Smrg/* 315 series and later only */ 227672b676d7Smrgstatic __inline void 227772b676d7Smrgset_hue(SISPtr pSiS, CARD8 hue) 227872b676d7Smrg{ 227972b676d7Smrg setvideoregmask(pSiS, Index_VI_Hue, (hue & 0x08) ? (hue ^ 0x07) : hue, 0x0F); 228072b676d7Smrg} 228172b676d7Smrg 228272b676d7Smrgstatic __inline void 228372b676d7Smrgset_disablegfx(SISPtr pSiS, Bool mybool, SISOverlayPtr pOverlay) 228472b676d7Smrg{ 228572b676d7Smrg /* This is not supported on M65x, 65x (x>0) or later */ 228672b676d7Smrg /* For CRT1 ONLY!!! */ 228772b676d7Smrg if((!(pSiS->ChipFlags & SiSCF_Is65x)) && 228872b676d7Smrg (pSiS->Chipset != PCI_CHIP_SIS660) && 228972b676d7Smrg (pSiS->Chipset != PCI_CHIP_SIS340) && 229072b676d7Smrg (pSiS->Chipset != PCI_CHIP_XGIXG20) && 229172b676d7Smrg (pSiS->Chipset != PCI_CHIP_XGIXG40)) { 229272b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc2, mybool ? 0x04 : 0x00, 0x04); 229372b676d7Smrg if(mybool) pOverlay->keyOP = VI_ROP_Always; 229472b676d7Smrg } 229572b676d7Smrg} 229672b676d7Smrg 229772b676d7Smrgstatic __inline void 229872b676d7Smrgset_disablegfxlr(SISPtr pSiS, Bool mybool, SISOverlayPtr pOverlay) 229972b676d7Smrg{ 230072b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc1, mybool ? 0x01 : 0x00, 0x01); 230172b676d7Smrg if(mybool) pOverlay->keyOP = VI_ROP_Always; 230272b676d7Smrg} 230372b676d7Smrg 230472b676d7Smrg#ifdef SIS_CP 230572b676d7Smrg SIS_CP_VIDEO_SUBS 230672b676d7Smrg#endif 230772b676d7Smrg 230872b676d7Smrg/********************************* 230972b676d7Smrg * Set main overlay registers * 231072b676d7Smrg *********************************/ 231172b676d7Smrg 231272b676d7Smrgstatic void 231372b676d7Smrgset_overlay(SISPtr pSiS, SISOverlayPtr pOverlay, SISPortPrivPtr pPriv, int index, int iscrt2) 231472b676d7Smrg{ 231572b676d7Smrg CARD8 h_over, v_over; 231672b676d7Smrg CARD16 top, bottom, left, right, pitch = 0; 231772b676d7Smrg CARD16 screenX, screenY; 231872b676d7Smrg CARD32 PSY; 231972b676d7Smrg int modeflags, totalPixels, confactor, sample, watchdog = 0; 232072b676d7Smrg 232172b676d7Smrg#ifdef SISMERGED 232272b676d7Smrg if(pSiS->MergedFB && iscrt2) { 232372b676d7Smrg screenX = pOverlay->currentmode2->HDisplay; 232472b676d7Smrg screenY = pOverlay->currentmode2->VDisplay; 232572b676d7Smrg modeflags = pOverlay->currentmode2->Flags; 232672b676d7Smrg top = pOverlay->dstBox2.y1; 232772b676d7Smrg bottom = pOverlay->dstBox2.y2; 232872b676d7Smrg left = pOverlay->dstBox2.x1; 232972b676d7Smrg right = pOverlay->dstBox2.x2; 233072b676d7Smrg pitch = pOverlay->pitch2 >> pPriv->shiftValue; 233172b676d7Smrg } else { 233272b676d7Smrg#endif 233372b676d7Smrg screenX = pOverlay->currentmode->HDisplay; 233472b676d7Smrg screenY = pOverlay->currentmode->VDisplay; 233572b676d7Smrg modeflags = pOverlay->currentmode->Flags; 233672b676d7Smrg top = pOverlay->dstBox.y1; 233772b676d7Smrg bottom = pOverlay->dstBox.y2; 233872b676d7Smrg left = pOverlay->dstBox.x1; 233972b676d7Smrg right = pOverlay->dstBox.x2; 234072b676d7Smrg pitch = pOverlay->pitch >> pPriv->shiftValue; 234172b676d7Smrg#ifdef SISMERGED 234272b676d7Smrg } 234372b676d7Smrg#endif 234472b676d7Smrg 234572b676d7Smrg if(bottom > screenY) bottom = screenY; 234672b676d7Smrg if(right > screenX) right = screenX; 234772b676d7Smrg 234872b676d7Smrg /* calculate contrast factor */ 234972b676d7Smrg totalPixels = (right - left) * (bottom - top); 235072b676d7Smrg confactor = (totalPixels - 10000) / 20000; 235172b676d7Smrg if(confactor > 3) confactor = 3; 235272b676d7Smrg switch(confactor) { 235372b676d7Smrg case 1: sample = 4096 << 10; break; 235472b676d7Smrg case 2: 235572b676d7Smrg case 3: sample = 8192 << 10; break; 235672b676d7Smrg default: sample = 2048 << 10; 235772b676d7Smrg } 235872b676d7Smrg sample /= totalPixels; 235972b676d7Smrg confactor <<= 6; 236072b676d7Smrg 236172b676d7Smrg /* Correct coordinates for doublescan/interlace modes */ 236272b676d7Smrg if( (modeflags & V_DBLSCAN) && 236372b676d7Smrg (!((pPriv->bridgeIsSlave || iscrt2) && (pSiS->MiscFlags & MISC_STNMODE))) ) { 236472b676d7Smrg /* DoubleScan modes require Y coordinates * 2 */ 236572b676d7Smrg top <<= 1; 236672b676d7Smrg bottom <<= 1; 236772b676d7Smrg } else if(modeflags & V_INTERLACE) { 236872b676d7Smrg /* Interlace modes require Y coordinates / 2 */ 236972b676d7Smrg top >>= 1; 237072b676d7Smrg bottom >>= 1; 237172b676d7Smrg } 237272b676d7Smrg 237372b676d7Smrg h_over = (((left >> 8) & 0x0f) | ((right >> 4) & 0xf0)); 237472b676d7Smrg v_over = (((top >> 8) & 0x0f) | ((bottom >> 4) & 0xf0)); 237572b676d7Smrg 237672b676d7Smrg /* set line buffer size */ 237772b676d7Smrg#ifdef SISMERGED 237872b676d7Smrg if(pSiS->MergedFB && iscrt2) { 237972b676d7Smrg setvideoreg(pSiS, Index_VI_Line_Buffer_Size, (CARD8)pOverlay->lineBufSize2); 238072b676d7Smrg if(pPriv->is340 || pPriv->is761 || pPriv->isXGI) { 238172b676d7Smrg setvideoreg(pSiS, Index_VI_Line_Buffer_Size_High, (CARD8)(pOverlay->lineBufSize2 >> 8)); 238272b676d7Smrg } 238372b676d7Smrg } else { 238472b676d7Smrg#endif 238572b676d7Smrg setvideoreg(pSiS, Index_VI_Line_Buffer_Size, (CARD8)pOverlay->lineBufSize); 238672b676d7Smrg if(pPriv->is340 || pPriv->is761 || pPriv->isXGI) { 238772b676d7Smrg setvideoreg(pSiS, Index_VI_Line_Buffer_Size_High, (CARD8)(pOverlay->lineBufSize >> 8)); 238872b676d7Smrg } 238972b676d7Smrg#ifdef SISMERGED 239072b676d7Smrg } 239172b676d7Smrg#endif 239272b676d7Smrg 239372b676d7Smrg /* set color key mode */ 239472b676d7Smrg setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, pOverlay->keyOP, 0x0f); 239572b676d7Smrg 239672b676d7Smrg /* We don't have to wait for vertical retrace in all cases */ 239772b676d7Smrg if(pPriv->mustwait) { 239872b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 239972b676d7Smrg 240072b676d7Smrg if(index) { 240172b676d7Smrg CARD16 mytop = getvideoreg(pSiS, Index_VI_Win_Ver_Disp_Start_Low); 240272b676d7Smrg mytop |= ((getvideoreg(pSiS, Index_VI_Win_Ver_Over) & 0x0f) << 8); 240372b676d7Smrg pOverlay->oldtop = mytop; 240472b676d7Smrg watchdog = 0xffff; 240572b676d7Smrg if(mytop < screenY - 2) { 240672b676d7Smrg do { 240772b676d7Smrg watchdog = get_scanline_CRT2(pSiS, pPriv); 240872b676d7Smrg } while((watchdog <= mytop) || (watchdog >= screenY)); 240972b676d7Smrg } 241072b676d7Smrg pOverlay->oldLine = watchdog; 241172b676d7Smrg } 241272b676d7Smrg 241372b676d7Smrg } else { 241472b676d7Smrg 241572b676d7Smrg watchdog = WATCHDOG_DELAY; 241672b676d7Smrg while(pOverlay->VBlankActiveFunc(pSiS, pPriv) && --watchdog); 241772b676d7Smrg watchdog = WATCHDOG_DELAY; 241872b676d7Smrg while((!pOverlay->VBlankActiveFunc(pSiS, pPriv)) && --watchdog); 241972b676d7Smrg 242072b676d7Smrg } 242172b676d7Smrg } 242272b676d7Smrg 242372b676d7Smrg /* Unlock address registers */ 242472b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x20, 0x20); 242572b676d7Smrg 242672b676d7Smrg /* Set destination window position */ 242772b676d7Smrg setvideoreg(pSiS, Index_VI_Win_Hor_Disp_Start_Low, (CARD8)left); 242872b676d7Smrg setvideoreg(pSiS, Index_VI_Win_Hor_Disp_End_Low, (CARD8)right); 242972b676d7Smrg setvideoreg(pSiS, Index_VI_Win_Hor_Over, (CARD8)h_over); 243072b676d7Smrg 243172b676d7Smrg setvideoreg(pSiS, Index_VI_Win_Ver_Disp_Start_Low, (CARD8)top); 243272b676d7Smrg setvideoreg(pSiS, Index_VI_Win_Ver_Disp_End_Low, (CARD8)bottom); 243372b676d7Smrg setvideoreg(pSiS, Index_VI_Win_Ver_Over, (CARD8)v_over); 243472b676d7Smrg 243572b676d7Smrg /* Contrast factor */ 243672b676d7Smrg setvideoregmask(pSiS, Index_VI_Contrast_Enh_Ctrl, (CARD8)confactor, 0xc0); 243772b676d7Smrg setvideoreg(pSiS, Index_VI_Contrast_Factor, sample); 243872b676d7Smrg 243972b676d7Smrg /* Set Y buf pitch */ 244072b676d7Smrg setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Pitch_Low, (CARD8)(pitch)); 244172b676d7Smrg setvideoregmask(pSiS, Index_VI_Disp_Y_UV_Buf_Pitch_Middle, (CARD8)(pitch >> 8), 0x0f); 244272b676d7Smrg 244372b676d7Smrg /* Set Y start address */ 244472b676d7Smrg#ifdef SISMERGED 244572b676d7Smrg if(pSiS->MergedFB && iscrt2) { 244672b676d7Smrg PSY = pOverlay->PSY2; 244772b676d7Smrg } else 244872b676d7Smrg#endif 244972b676d7Smrg PSY = pOverlay->PSY; 245072b676d7Smrg 245172b676d7Smrg setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Start_Low, (CARD8)(PSY)); 245272b676d7Smrg setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Start_Middle, (CARD8)(PSY >> 8)); 245372b676d7Smrg setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Start_High, (CARD8)(PSY >> 16)); 245472b676d7Smrg 245572b676d7Smrg /* Set 315 series overflow bits for Y plane */ 245672b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 245772b676d7Smrg setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Pitch_High, (CARD8)(pitch >> 12)); 245872b676d7Smrg setvideoreg(pSiS, Index_VI_Y_Buf_Start_Over, ((CARD8)(PSY >> 24) & 0x03)); 245972b676d7Smrg } 246072b676d7Smrg 246172b676d7Smrg /* Set U/V data if using planar formats */ 246272b676d7Smrg if(pOverlay->planar) { 246372b676d7Smrg 246472b676d7Smrg CARD32 PSU = pOverlay->PSU; 246572b676d7Smrg CARD32 PSV = pOverlay->PSV; 246672b676d7Smrg 246772b676d7Smrg#ifdef SISMERGED 246872b676d7Smrg if(pSiS->MergedFB && iscrt2) { 246972b676d7Smrg PSU = pOverlay->PSU2; 247072b676d7Smrg PSV = pOverlay->PSV2; 247172b676d7Smrg } 247272b676d7Smrg#endif 247372b676d7Smrg 247472b676d7Smrg if(pOverlay->planar_shiftpitch) pitch >>= 1; 247572b676d7Smrg 247672b676d7Smrg /* Set U/V pitch */ 247772b676d7Smrg setvideoreg(pSiS, Index_VI_Disp_UV_Buf_Pitch_Low, (CARD8)pitch); 247872b676d7Smrg setvideoregmask(pSiS, Index_VI_Disp_Y_UV_Buf_Pitch_Middle, (CARD8)(pitch >> 4), 0xf0); 247972b676d7Smrg 248072b676d7Smrg /* Set U/V start address */ 248172b676d7Smrg setvideoreg(pSiS, Index_VI_U_Buf_Start_Low, (CARD8)PSU); 248272b676d7Smrg setvideoreg(pSiS, Index_VI_U_Buf_Start_Middle,(CARD8)(PSU >> 8)); 248372b676d7Smrg setvideoreg(pSiS, Index_VI_U_Buf_Start_High, (CARD8)(PSU >> 16)); 248472b676d7Smrg 248572b676d7Smrg setvideoreg(pSiS, Index_VI_V_Buf_Start_Low, (CARD8)PSV); 248672b676d7Smrg setvideoreg(pSiS, Index_VI_V_Buf_Start_Middle,(CARD8)(PSV >> 8)); 248772b676d7Smrg setvideoreg(pSiS, Index_VI_V_Buf_Start_High, (CARD8)(PSV >> 16)); 248872b676d7Smrg 248972b676d7Smrg /* 315 series overflow bits */ 249072b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 249172b676d7Smrg setvideoreg(pSiS, Index_VI_Disp_UV_Buf_Pitch_High, (CARD8)(pitch >> 12)); 249272b676d7Smrg setvideoreg(pSiS, Index_VI_U_Buf_Start_Over, ((CARD8)(PSU >> 24) & 0x03)); 249372b676d7Smrg if(pPriv->is661741760) { 249472b676d7Smrg setvideoregmask(pSiS, Index_VI_V_Buf_Start_Over, ((CARD8)(PSV >> 24) & 0x03), 0xc3); 249572b676d7Smrg } else { 249672b676d7Smrg setvideoreg(pSiS, Index_VI_V_Buf_Start_Over, ((CARD8)(PSV >> 24) & 0x03)); 249772b676d7Smrg } 249872b676d7Smrg } 249972b676d7Smrg } 250072b676d7Smrg 250172b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc1, pOverlay->bobEnable, 0x1a); 250272b676d7Smrg 250372b676d7Smrg /* Lock the address registers */ 250472b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x20); 250572b676d7Smrg 250672b676d7Smrg /* Set scale factor */ 250772b676d7Smrg#ifdef SISMERGED 250872b676d7Smrg if(pSiS->MergedFB && iscrt2) { 250972b676d7Smrg setvideoreg(pSiS, Index_VI_Hor_Post_Up_Scale_Low, (CARD8)(pOverlay->HUSF2)); 251072b676d7Smrg setvideoreg(pSiS, Index_VI_Hor_Post_Up_Scale_High,(CARD8)((pOverlay->HUSF2) >> 8)); 251172b676d7Smrg setvideoreg(pSiS, Index_VI_Ver_Up_Scale_Low, (CARD8)(pOverlay->VUSF2)); 251272b676d7Smrg setvideoreg(pSiS, Index_VI_Ver_Up_Scale_High, (CARD8)((pOverlay->VUSF2) >> 8)); 251372b676d7Smrg 251472b676d7Smrg setvideoregmask(pSiS, Index_VI_Scale_Control, (pOverlay->IntBit2 << 3) | 251572b676d7Smrg (pOverlay->wHPre2), 0x7f); 251672b676d7Smrg 251772b676d7Smrg if(pPriv->havetapscaler) { 251872b676d7Smrg if((pOverlay->tap_scale2 != pOverlay->tap_scale2_old) || pPriv->mustresettap2) { 251972b676d7Smrg set_dda_regs(pSiS, pOverlay->tap_scale2); 252072b676d7Smrg pOverlay->tap_scale2_old = pOverlay->tap_scale2; 252172b676d7Smrg pPriv->mustresettap2 = FALSE; 252272b676d7Smrg } 252372b676d7Smrg } 252472b676d7Smrg } else { 252572b676d7Smrg#endif 252672b676d7Smrg setvideoreg(pSiS, Index_VI_Hor_Post_Up_Scale_Low, (CARD8)(pOverlay->HUSF)); 252772b676d7Smrg setvideoreg(pSiS, Index_VI_Hor_Post_Up_Scale_High,(CARD8)((pOverlay->HUSF) >> 8)); 252872b676d7Smrg setvideoreg(pSiS, Index_VI_Ver_Up_Scale_Low, (CARD8)(pOverlay->VUSF)); 252972b676d7Smrg setvideoreg(pSiS, Index_VI_Ver_Up_Scale_High, (CARD8)((pOverlay->VUSF) >> 8)); 253072b676d7Smrg 253172b676d7Smrg setvideoregmask(pSiS, Index_VI_Scale_Control, (pOverlay->IntBit << 3) | 253272b676d7Smrg (pOverlay->wHPre), 0x7f); 253372b676d7Smrg if(pPriv->havetapscaler) { 253472b676d7Smrg if((pOverlay->tap_scale != pOverlay->tap_scale_old) || pPriv->mustresettap) { 253572b676d7Smrg set_dda_regs(pSiS, pOverlay->tap_scale); 253672b676d7Smrg pOverlay->tap_scale_old = pOverlay->tap_scale; 253772b676d7Smrg pPriv->mustresettap = FALSE; 253872b676d7Smrg } 253972b676d7Smrg } 254072b676d7Smrg#ifdef SISMERGED 254172b676d7Smrg } 254272b676d7Smrg#endif 254372b676d7Smrg 254472b676d7Smrg} 254572b676d7Smrg 254672b676d7Smrg/********************************* 254772b676d7Smrg * Shut down overlay * 254872b676d7Smrg *********************************/ 254972b676d7Smrg 255072b676d7Smrg/* Overlay MUST NOT be switched off while beam is over it */ 255172b676d7Smrgstatic void 255272b676d7Smrgclose_overlay(SISPtr pSiS, SISPortPrivPtr pPriv) 255372b676d7Smrg{ 255472b676d7Smrg int watchdog; 255572b676d7Smrg 255672b676d7Smrg if(!pPriv->overlayStatus) return; 255772b676d7Smrg 255872b676d7Smrg pPriv->overlayStatus = FALSE; 255972b676d7Smrg 256072b676d7Smrg pPriv->mustresettap = TRUE; 256172b676d7Smrg#ifdef SISMERGED 256272b676d7Smrg pPriv->mustresettap2 = TRUE; 256372b676d7Smrg#endif 256472b676d7Smrg 256572b676d7Smrg if(pPriv->displayMode & (DISPMODE_MIRROR | DISPMODE_SINGLE2)) { 256672b676d7Smrg 256772b676d7Smrg /* CRT2: MIRROR or SINGLE2 256872b676d7Smrg * 1 overlay: Uses overlay 0 256972b676d7Smrg * 2 overlays: Uses Overlay 1 if MIRROR or DUAL HEAD 257072b676d7Smrg * Uses Overlay 0 if SINGLE2 and not DUAL HEAD 257172b676d7Smrg */ 257272b676d7Smrg 257372b676d7Smrg if(pPriv->hasTwoOverlays) { 257472b676d7Smrg 257572b676d7Smrg if((pPriv->dualHeadMode) || (pPriv->displayMode == DISPMODE_MIRROR)) { 257672b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, 0x01); 257772b676d7Smrg } else { 257872b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0x01); 257972b676d7Smrg } 258072b676d7Smrg 258172b676d7Smrg } else if(pPriv->displayMode == DISPMODE_SINGLE2) { 258272b676d7Smrg 258372b676d7Smrg#ifdef SISDUALHEAD 258472b676d7Smrg if(pPriv->dualHeadMode) { 258572b676d7Smrg /* Check if overlay already grabbed by other head */ 258672b676d7Smrg if(!(getsrreg(pSiS, 0x06) & 0x40)) return; 258772b676d7Smrg } 258872b676d7Smrg#endif 258972b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0x01); 259072b676d7Smrg 259172b676d7Smrg } 259272b676d7Smrg 259372b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x01); 259472b676d7Smrg 259572b676d7Smrg watchdog = WATCHDOG_DELAY; 259672b676d7Smrg while((!vblank_active_CRT2(pSiS, pPriv)) && --watchdog); 259772b676d7Smrg watchdog = WATCHDOG_DELAY; 259872b676d7Smrg while(vblank_active_CRT2(pSiS, pPriv) && --watchdog); 259972b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02); 260072b676d7Smrg watchdog = WATCHDOG_DELAY; 260172b676d7Smrg while((!vblank_active_CRT2(pSiS, pPriv)) && --watchdog); 260272b676d7Smrg watchdog = WATCHDOG_DELAY; 260372b676d7Smrg while(vblank_active_CRT2(pSiS, pPriv) && --watchdog); 260472b676d7Smrg 260572b676d7Smrg#ifdef SIS_CP 260672b676d7Smrg SIS_CP_RESET_CP 260772b676d7Smrg#endif 260872b676d7Smrg 260972b676d7Smrg } 261072b676d7Smrg 261172b676d7Smrg if(pPriv->displayMode & (DISPMODE_SINGLE1 | DISPMODE_MIRROR)) { 261272b676d7Smrg 261372b676d7Smrg /* CRT1: Always uses overlay 0 261472b676d7Smrg */ 261572b676d7Smrg 261672b676d7Smrg#ifdef SISDUALHEAD 261772b676d7Smrg if(pPriv->dualHeadMode) { 261872b676d7Smrg if(!pPriv->hasTwoOverlays) { 261972b676d7Smrg /* Check if overlay already grabbed by other head */ 262072b676d7Smrg if(getsrreg(pSiS, 0x06) & 0x40) return; 262172b676d7Smrg } 262272b676d7Smrg } 262372b676d7Smrg#endif 262472b676d7Smrg 262572b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0x05); 262672b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x01); 262772b676d7Smrg 262872b676d7Smrg watchdog = WATCHDOG_DELAY; 262972b676d7Smrg while((!vblank_active_CRT1(pSiS, pPriv)) && --watchdog); 263072b676d7Smrg watchdog = WATCHDOG_DELAY; 263172b676d7Smrg while(vblank_active_CRT1(pSiS, pPriv) && --watchdog); 263272b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02); 263372b676d7Smrg watchdog = WATCHDOG_DELAY; 263472b676d7Smrg while((!vblank_active_CRT1(pSiS, pPriv)) && --watchdog); 263572b676d7Smrg watchdog = WATCHDOG_DELAY; 263672b676d7Smrg while(vblank_active_CRT1(pSiS, pPriv) && --watchdog); 263772b676d7Smrg 263872b676d7Smrg } 263972b676d7Smrg} 264072b676d7Smrg 264172b676d7Smrg/********************************* 264272b676d7Smrg * DisplayVideo() * 264372b676d7Smrg *********************************/ 264472b676d7Smrg 264572b676d7Smrgstatic void 264672b676d7SmrgSISDisplayVideo(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) 264772b676d7Smrg{ 264872b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 264972b676d7Smrg#ifdef SISDUALHEAD 265072b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 265172b676d7Smrg#endif 265272b676d7Smrg short srcPitch = pPriv->srcPitch; 265372b676d7Smrg short height = pPriv->height; 265472b676d7Smrg UShort screenwidth; 265572b676d7Smrg SISOverlayRec overlay; 265672b676d7Smrg int srcOffsetX = 0, srcOffsetY = 0; 265772b676d7Smrg int sx = 0, sy = 0, watchdog; 265872b676d7Smrg int index = 0, iscrt2 = 0; 265972b676d7Smrg#ifdef SISMERGED 266072b676d7Smrg UChar temp; 266172b676d7Smrg UShort screen2width = 0; 266272b676d7Smrg int srcOffsetX2 = 0, srcOffsetY2 = 0; 266372b676d7Smrg int sx2 = 0, sy2 = 0; 266472b676d7Smrg#endif 266572b676d7Smrg 266672b676d7Smrg /* Determine whether we have two overlays or only one */ 266772b676d7Smrg set_hastwooverlays(pSiS, pPriv); 266872b676d7Smrg 266972b676d7Smrg pPriv->NoOverlay = FALSE; 267072b676d7Smrg#ifdef SISDUALHEAD 267172b676d7Smrg if(pPriv->dualHeadMode) { 267272b676d7Smrg if(!pPriv->hasTwoOverlays) { 267372b676d7Smrg if(pSiS->SecondHead) { 267472b676d7Smrg if(pSiSEnt->curxvcrtnum != 0) { 267572b676d7Smrg if(pPriv->overlayStatus) { 267672b676d7Smrg close_overlay(pSiS, pPriv); 267772b676d7Smrg } 267872b676d7Smrg pPriv->NoOverlay = TRUE; 267972b676d7Smrg return; 268072b676d7Smrg } 268172b676d7Smrg } else { 268272b676d7Smrg if(pSiSEnt->curxvcrtnum != 1) { 268372b676d7Smrg if(pPriv->overlayStatus) { 268472b676d7Smrg close_overlay(pSiS, pPriv); 268572b676d7Smrg } 268672b676d7Smrg pPriv->NoOverlay = TRUE; 268772b676d7Smrg return; 268872b676d7Smrg } 268972b676d7Smrg } 269072b676d7Smrg } 269172b676d7Smrg } 269272b676d7Smrg#endif 269372b676d7Smrg 269472b676d7Smrg /* setup dispmode (MIRROR, SINGLEx) */ 269572b676d7Smrg set_dispmode(pScrn, pPriv); 269672b676d7Smrg 269772b676d7Smrg /* Check if overlay is supported with current mode */ 269872b676d7Smrg#ifdef SISMERGED 269972b676d7Smrg if(!pSiS->MergedFB) { 270072b676d7Smrg#endif 270172b676d7Smrg if( ((pPriv->displayMode & DISPMODE_MIRROR) && 270272b676d7Smrg ((pSiS->MiscFlags & (MISC_CRT1OVERLAY|MISC_CRT2OVERLAY)) != (MISC_CRT1OVERLAY|MISC_CRT2OVERLAY))) || 270372b676d7Smrg ((pPriv->displayMode & DISPMODE_SINGLE1) && 270472b676d7Smrg (!(pSiS->MiscFlags & MISC_CRT1OVERLAY))) || 270572b676d7Smrg ((pPriv->displayMode & DISPMODE_SINGLE2) && 270672b676d7Smrg (!(pSiS->MiscFlags & MISC_CRT2OVERLAY))) ) { 270772b676d7Smrg if(pPriv->overlayStatus) { 270872b676d7Smrg close_overlay(pSiS, pPriv); 270972b676d7Smrg } 271072b676d7Smrg pPriv->NoOverlay = TRUE; 271172b676d7Smrg return; 271272b676d7Smrg } 271372b676d7Smrg#ifdef SISMERGED 271472b676d7Smrg } 271572b676d7Smrg#endif 271672b676d7Smrg 271772b676d7Smrg memset(&overlay, 0, sizeof(overlay)); 271872b676d7Smrg 271972b676d7Smrg overlay.pixelFormat = pPriv->id; 272072b676d7Smrg overlay.pitch = overlay.origPitch = srcPitch; 272172b676d7Smrg if(pPriv->usechromakey) { 272272b676d7Smrg overlay.keyOP = (pPriv->insidechromakey) ? VI_ROP_ChromaKey : VI_ROP_NotChromaKey; 272372b676d7Smrg } else { 272472b676d7Smrg overlay.keyOP = VI_ROP_DestKey; 272572b676d7Smrg } 272672b676d7Smrg 272772b676d7Smrg#ifdef SISDEINT 272872b676d7Smrg switch(pPriv->deinterlacemethod) { 272972b676d7Smrg case 1: 273072b676d7Smrg overlay.bobEnable = 0x02; 273172b676d7Smrg /* overlay.bobEnable |= (pPriv->currentBuf) ? 0x00 : 0x10; */ 273272b676d7Smrg break; 273372b676d7Smrg case 2: 273472b676d7Smrg overlay.bobEnable = 0x08; 273572b676d7Smrg /* overlay.bobEnable |= (pPriv->currentBuf) ? 0x00 : 0x10; */ 273672b676d7Smrg break; 273772b676d7Smrg case 3: 273872b676d7Smrg overlay.bobEnable = 0x0a; 273972b676d7Smrg /* overlay.bobEnable |= (pPriv->currentBuf) ? 0x00 : 0x10; */ 274072b676d7Smrg break; 274172b676d7Smrg default: 274272b676d7Smrg#endif 274372b676d7Smrg overlay.bobEnable = 0x00; /* Disable BOB de-interlacer */ 274472b676d7Smrg#ifdef SISDEINT 274572b676d7Smrg } 274672b676d7Smrg#endif 274772b676d7Smrg 274872b676d7Smrg#ifdef SISMERGED 274972b676d7Smrg if(pSiS->MergedFB) { 275072b676d7Smrg overlay.DoFirst = TRUE; 275172b676d7Smrg overlay.DoSecond = TRUE; 275272b676d7Smrg overlay.pitch2 = overlay.origPitch; 275372b676d7Smrg overlay.currentmode = ((SiSMergedDisplayModePtr)pSiS->CurrentLayout.mode->Private)->CRT1; 275472b676d7Smrg overlay.currentmode2 = ((SiSMergedDisplayModePtr)pSiS->CurrentLayout.mode->Private)->CRT2; 275572b676d7Smrg overlay.SCREENheight = overlay.currentmode->VDisplay; 275672b676d7Smrg overlay.SCREENheight2 = overlay.currentmode2->VDisplay; 275772b676d7Smrg screenwidth = overlay.currentmode->HDisplay; 275872b676d7Smrg screen2width = overlay.currentmode2->HDisplay; 275972b676d7Smrg overlay.dstBox.x1 = pPriv->drw_x - pSiS->CRT1frameX0; 276072b676d7Smrg overlay.dstBox.x2 = overlay.dstBox.x1 + pPriv->drw_w; 276172b676d7Smrg overlay.dstBox.y1 = pPriv->drw_y - pSiS->CRT1frameY0; 276272b676d7Smrg overlay.dstBox.y2 = overlay.dstBox.y1 + pPriv->drw_h; 276372b676d7Smrg overlay.dstBox2.x1 = pPriv->drw_x - pSiS->CRT2pScrn->frameX0; 276472b676d7Smrg overlay.dstBox2.x2 = overlay.dstBox2.x1 + pPriv->drw_w; 276572b676d7Smrg overlay.dstBox2.y1 = pPriv->drw_y - pSiS->CRT2pScrn->frameY0; 276672b676d7Smrg overlay.dstBox2.y2 = overlay.dstBox2.y1 + pPriv->drw_h; 276772b676d7Smrg } else { 276872b676d7Smrg#endif 276972b676d7Smrg overlay.currentmode = pSiS->CurrentLayout.mode; 277072b676d7Smrg overlay.SCREENheight = overlay.currentmode->VDisplay; 277172b676d7Smrg screenwidth = overlay.currentmode->HDisplay; 277272b676d7Smrg overlay.dstBox.x1 = pPriv->drw_x - pScrn->frameX0; 277372b676d7Smrg overlay.dstBox.x2 = pPriv->drw_x + pPriv->drw_w - pScrn->frameX0; 277472b676d7Smrg overlay.dstBox.y1 = pPriv->drw_y - pScrn->frameY0; 277572b676d7Smrg overlay.dstBox.y2 = pPriv->drw_y + pPriv->drw_h - pScrn->frameY0; 277672b676d7Smrg#ifdef SISMERGED 277772b676d7Smrg } 277872b676d7Smrg#endif 277972b676d7Smrg 278072b676d7Smrg /* Note: x2/y2 is actually real coordinate + 1 */ 278172b676d7Smrg 278272b676d7Smrg if((overlay.dstBox.x1 >= overlay.dstBox.x2) || 278372b676d7Smrg (overlay.dstBox.y1 >= overlay.dstBox.y2)) { 278472b676d7Smrg#ifdef SISMERGED 278572b676d7Smrg if(pSiS->MergedFB) overlay.DoFirst = FALSE; 278672b676d7Smrg else 278772b676d7Smrg#endif 278872b676d7Smrg return; 278972b676d7Smrg } 279072b676d7Smrg 279172b676d7Smrg if((overlay.dstBox.x2 <= 0) || (overlay.dstBox.y2 <= 0)) { 279272b676d7Smrg#ifdef SISMERGED 279372b676d7Smrg if(pSiS->MergedFB) overlay.DoFirst = FALSE; 279472b676d7Smrg else 279572b676d7Smrg#endif 279672b676d7Smrg return; 279772b676d7Smrg } 279872b676d7Smrg 279972b676d7Smrg if((overlay.dstBox.x1 >= screenwidth) || (overlay.dstBox.y1 >= overlay.SCREENheight)) { 280072b676d7Smrg#ifdef SISMERGED 280172b676d7Smrg if(pSiS->MergedFB) overlay.DoFirst = FALSE; 280272b676d7Smrg else 280372b676d7Smrg#endif 280472b676d7Smrg return; 280572b676d7Smrg } 280672b676d7Smrg 280772b676d7Smrg#ifdef SISMERGED 280872b676d7Smrg if(pSiS->MergedFB) { 280972b676d7Smrg /* Check if dotclock is within limits for CRT1 */ 281072b676d7Smrg if(pPriv->displayMode & (DISPMODE_SINGLE1 | DISPMODE_MIRROR)) { 281172b676d7Smrg if(!(pSiS->MiscFlags & MISC_CRT1OVERLAY)) { 281272b676d7Smrg overlay.DoFirst = FALSE; 281372b676d7Smrg } 281472b676d7Smrg } 281572b676d7Smrg } 281672b676d7Smrg#endif 281772b676d7Smrg 281872b676d7Smrg if(overlay.dstBox.x1 < 0) { 281972b676d7Smrg srcOffsetX = pPriv->src_w * (-overlay.dstBox.x1) / pPriv->drw_w; 282072b676d7Smrg overlay.dstBox.x1 = 0; 282172b676d7Smrg } 282272b676d7Smrg if(overlay.dstBox.y1 < 0) { 282372b676d7Smrg srcOffsetY = pPriv->src_h * (-overlay.dstBox.y1) / pPriv->drw_h; 282472b676d7Smrg overlay.dstBox.y1 = 0; 282572b676d7Smrg } 282672b676d7Smrg 282772b676d7Smrg if((overlay.dstBox.x1 >= overlay.dstBox.x2 - 2) || 282872b676d7Smrg (overlay.dstBox.x1 >= screenwidth - 2) || 282972b676d7Smrg (overlay.dstBox.y1 >= overlay.dstBox.y2)) { 283072b676d7Smrg#ifdef SISMERGED 283172b676d7Smrg if(pSiS->MergedFB) overlay.DoFirst = FALSE; 283272b676d7Smrg else 283372b676d7Smrg#endif 283472b676d7Smrg return; 283572b676d7Smrg } 283672b676d7Smrg 283772b676d7Smrg#ifdef SISMERGED 283872b676d7Smrg if(pSiS->MergedFB) { 283972b676d7Smrg if((overlay.dstBox2.x2 <= 0) || (overlay.dstBox2.y2 <= 0)) 284072b676d7Smrg overlay.DoSecond = FALSE; 284172b676d7Smrg 284272b676d7Smrg if((overlay.dstBox2.x1 >= screen2width) || (overlay.dstBox2.y1 >= overlay.SCREENheight2)) 284372b676d7Smrg overlay.DoSecond = FALSE; 284472b676d7Smrg 284572b676d7Smrg if(overlay.dstBox2.x1 < 0) { 284672b676d7Smrg srcOffsetX2 = pPriv->src_w * (-overlay.dstBox2.x1) / pPriv->drw_w; 284772b676d7Smrg overlay.dstBox2.x1 = 0; 284872b676d7Smrg } 284972b676d7Smrg 285072b676d7Smrg if(overlay.dstBox2.y1 < 0) { 285172b676d7Smrg srcOffsetY2 = pPriv->src_h * (-overlay.dstBox2.y1) / pPriv->drw_h; 285272b676d7Smrg overlay.dstBox2.y1 = 0; 285372b676d7Smrg } 285472b676d7Smrg 285572b676d7Smrg if((overlay.dstBox2.x1 >= overlay.dstBox2.x2 - 2) || 285672b676d7Smrg (overlay.dstBox2.x1 >= screen2width - 2) || 285772b676d7Smrg (overlay.dstBox2.y1 >= overlay.dstBox2.y2)) 285872b676d7Smrg overlay.DoSecond = FALSE; 285972b676d7Smrg 286072b676d7Smrg /* Check if dotclock is within limits for CRT2 */ 286172b676d7Smrg if(pPriv->displayMode & (DISPMODE_SINGLE2 | DISPMODE_MIRROR)) { 286272b676d7Smrg if(!(pSiS->MiscFlags & MISC_CRT2OVERLAY)) { 286372b676d7Smrg overlay.DoSecond = FALSE; 286472b676d7Smrg } 286572b676d7Smrg } 286672b676d7Smrg 286772b676d7Smrg /* If neither overlay is to be displayed, disable them if they are currently enabled */ 286872b676d7Smrg if((!overlay.DoFirst) && (!overlay.DoSecond)) { 286972b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0x05); 287072b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x01); 287172b676d7Smrg temp = getvideoreg(pSiS,Index_VI_Control_Misc0); 287272b676d7Smrg if(temp & 0x02) { 287372b676d7Smrg watchdog = WATCHDOG_DELAY; 287472b676d7Smrg if(pPriv->hasTwoOverlays) { 287572b676d7Smrg while((!vblank_active_CRT1(pSiS, pPriv)) && --watchdog); 287672b676d7Smrg watchdog = WATCHDOG_DELAY; 287772b676d7Smrg while(vblank_active_CRT1(pSiS, pPriv) && --watchdog); 287872b676d7Smrg } else { 287972b676d7Smrg temp = getsrreg(pSiS, 0x06); 288072b676d7Smrg if(!(temp & 0x40)) { 288172b676d7Smrg while((!vblank_active_CRT1(pSiS, pPriv)) && --watchdog); 288272b676d7Smrg watchdog = WATCHDOG_DELAY; 288372b676d7Smrg while(vblank_active_CRT1(pSiS, pPriv) && --watchdog); 288472b676d7Smrg } else { 288572b676d7Smrg while((!vblank_active_CRT2(pSiS, pPriv)) && --watchdog); 288672b676d7Smrg watchdog = WATCHDOG_DELAY; 288772b676d7Smrg while(vblank_active_CRT2(pSiS, pPriv) && --watchdog); 288872b676d7Smrg } 288972b676d7Smrg } 289072b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02); 289172b676d7Smrg } 289272b676d7Smrg if(pPriv->hasTwoOverlays) { 289372b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, 0x01); 289472b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x01); 289572b676d7Smrg temp = getvideoreg(pSiS,Index_VI_Control_Misc0); 289672b676d7Smrg if(temp & 0x02) { 289772b676d7Smrg watchdog = WATCHDOG_DELAY; 289872b676d7Smrg while((!vblank_active_CRT2(pSiS, pPriv)) && --watchdog); 289972b676d7Smrg watchdog = WATCHDOG_DELAY; 290072b676d7Smrg while(vblank_active_CRT2(pSiS, pPriv) && --watchdog); 290172b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02); 290272b676d7Smrg } 290372b676d7Smrg } 290472b676d7Smrg pPriv->overlayStatus = FALSE; 290572b676d7Smrg return; 290672b676d7Smrg } 290772b676d7Smrg } 290872b676d7Smrg#endif 290972b676d7Smrg 291072b676d7Smrg switch(pPriv->id) { 291172b676d7Smrg 291272b676d7Smrg case PIXEL_FMT_YV12: 291372b676d7Smrg overlay.planar = 1; 291472b676d7Smrg overlay.planar_shiftpitch = 1; 291572b676d7Smrg#ifdef SISMERGED 291672b676d7Smrg if((!pSiS->MergedFB) || (overlay.DoFirst)) { 291772b676d7Smrg#endif 291872b676d7Smrg sx = (pPriv->src_x + srcOffsetX) & ~7; 291972b676d7Smrg sy = (pPriv->src_y + srcOffsetY) & ~1; 292072b676d7Smrg overlay.PSY = pPriv->bufAddr[pPriv->currentBuf] + sx + sy*srcPitch; 292172b676d7Smrg overlay.PSV = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch + ((sx + sy*srcPitch/2) >> 1); 292272b676d7Smrg overlay.PSU = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch*5/4 + ((sx + sy*srcPitch/2) >> 1); 292372b676d7Smrg overlay.PSY += FBOFFSET; 292472b676d7Smrg overlay.PSV += FBOFFSET; 292572b676d7Smrg overlay.PSU += FBOFFSET; 292672b676d7Smrg overlay.PSY >>= pPriv->shiftValue; 292772b676d7Smrg overlay.PSV >>= pPriv->shiftValue; 292872b676d7Smrg overlay.PSU >>= pPriv->shiftValue; 292972b676d7Smrg#ifdef SISMERGED 293072b676d7Smrg } 293172b676d7Smrg if((pSiS->MergedFB) && (overlay.DoSecond)) { 293272b676d7Smrg sx2 = (pPriv->src_x + srcOffsetX2) & ~7; 293372b676d7Smrg sy2 = (pPriv->src_y + srcOffsetY2) & ~1; 293472b676d7Smrg overlay.PSY2 = pPriv->bufAddr[pPriv->currentBuf] + sx2 + sy2*srcPitch; 293572b676d7Smrg overlay.PSV2 = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch + ((sx2 + sy2*srcPitch/2) >> 1); 293672b676d7Smrg overlay.PSU2 = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch*5/4 + ((sx2 + sy2*srcPitch/2) >> 1); 293772b676d7Smrg overlay.PSY2 += FBOFFSET; 293872b676d7Smrg overlay.PSV2 += FBOFFSET; 293972b676d7Smrg overlay.PSU2 += FBOFFSET; 294072b676d7Smrg overlay.PSY2 >>= pPriv->shiftValue; 294172b676d7Smrg overlay.PSV2 >>= pPriv->shiftValue; 294272b676d7Smrg overlay.PSU2 >>= pPriv->shiftValue; 294372b676d7Smrg } 294472b676d7Smrg#endif 294572b676d7Smrg break; 294672b676d7Smrg 294772b676d7Smrg case PIXEL_FMT_I420: 294872b676d7Smrg overlay.planar = 1; 294972b676d7Smrg overlay.planar_shiftpitch = 1; 295072b676d7Smrg#ifdef SISMERGED 295172b676d7Smrg if((!pSiS->MergedFB) || (overlay.DoFirst)) { 295272b676d7Smrg#endif 295372b676d7Smrg sx = (pPriv->src_x + srcOffsetX) & ~7; 295472b676d7Smrg sy = (pPriv->src_y + srcOffsetY) & ~1; 295572b676d7Smrg overlay.PSY = pPriv->bufAddr[pPriv->currentBuf] + sx + sy*srcPitch; 295672b676d7Smrg overlay.PSV = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch*5/4 + ((sx + sy*srcPitch/2) >> 1); 295772b676d7Smrg overlay.PSU = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch + ((sx + sy*srcPitch/2) >> 1); 295872b676d7Smrg overlay.PSY += FBOFFSET; 295972b676d7Smrg overlay.PSV += FBOFFSET; 296072b676d7Smrg overlay.PSU += FBOFFSET; 296172b676d7Smrg overlay.PSY >>= pPriv->shiftValue; 296272b676d7Smrg overlay.PSV >>= pPriv->shiftValue; 296372b676d7Smrg overlay.PSU >>= pPriv->shiftValue; 296472b676d7Smrg#ifdef SISMERGED 296572b676d7Smrg } 296672b676d7Smrg if((pSiS->MergedFB) && (overlay.DoSecond)) { 296772b676d7Smrg sx2 = (pPriv->src_x + srcOffsetX2) & ~7; 296872b676d7Smrg sy2 = (pPriv->src_y + srcOffsetY2) & ~1; 296972b676d7Smrg overlay.PSY2 = pPriv->bufAddr[pPriv->currentBuf] + sx2 + sy2*srcPitch; 297072b676d7Smrg overlay.PSV2 = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch*5/4 + ((sx2 + sy2*srcPitch/2) >> 1); 297172b676d7Smrg overlay.PSU2 = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch + ((sx2 + sy2*srcPitch/2) >> 1); 297272b676d7Smrg overlay.PSY2 += FBOFFSET; 297372b676d7Smrg overlay.PSV2 += FBOFFSET; 297472b676d7Smrg overlay.PSU2 += FBOFFSET; 297572b676d7Smrg overlay.PSY2 >>= pPriv->shiftValue; 297672b676d7Smrg overlay.PSV2 >>= pPriv->shiftValue; 297772b676d7Smrg overlay.PSU2 >>= pPriv->shiftValue; 297872b676d7Smrg } 297972b676d7Smrg#endif 298072b676d7Smrg break; 298172b676d7Smrg 298272b676d7Smrg case PIXEL_FMT_NV12: 298372b676d7Smrg case PIXEL_FMT_NV21: 298472b676d7Smrg overlay.planar = 1; 298572b676d7Smrg overlay.planar_shiftpitch = 0; 298672b676d7Smrg#ifdef SISMERGED 298772b676d7Smrg if((!pSiS->MergedFB) || (overlay.DoFirst)) { 298872b676d7Smrg#endif 298972b676d7Smrg sx = (pPriv->src_x + srcOffsetX) & ~7; 299072b676d7Smrg sy = (pPriv->src_y + srcOffsetY) & ~1; 299172b676d7Smrg overlay.PSY = pPriv->bufAddr[pPriv->currentBuf] + sx + sy*srcPitch; 299272b676d7Smrg overlay.PSV = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch + ((sx + sy*srcPitch/2) >> 1); 299372b676d7Smrg overlay.PSY += FBOFFSET; 299472b676d7Smrg overlay.PSV += FBOFFSET; 299572b676d7Smrg overlay.PSY >>= pPriv->shiftValue; 299672b676d7Smrg overlay.PSV >>= pPriv->shiftValue; 299772b676d7Smrg overlay.PSU = overlay.PSV; 299872b676d7Smrg#ifdef SISMERGED 299972b676d7Smrg } 300072b676d7Smrg if((pSiS->MergedFB) && (overlay.DoSecond)) { 300172b676d7Smrg sx2 = (pPriv->src_x + srcOffsetX2) & ~7; 300272b676d7Smrg sy2 = (pPriv->src_y + srcOffsetY2) & ~1; 300372b676d7Smrg overlay.PSY2 = pPriv->bufAddr[pPriv->currentBuf] + sx2 + sy2*srcPitch; 300472b676d7Smrg overlay.PSV2 = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch + ((sx2 + sy2*srcPitch/2) >> 1); 300572b676d7Smrg overlay.PSY2 += FBOFFSET; 300672b676d7Smrg overlay.PSV2 += FBOFFSET; 300772b676d7Smrg overlay.PSY2 >>= pPriv->shiftValue; 300872b676d7Smrg overlay.PSV2 >>= pPriv->shiftValue; 300972b676d7Smrg overlay.PSU2 = overlay.PSV2; 301072b676d7Smrg } 301172b676d7Smrg#endif 301272b676d7Smrg break; 301372b676d7Smrg 301472b676d7Smrg case PIXEL_FMT_YUY2: 301572b676d7Smrg case PIXEL_FMT_UYVY: 301672b676d7Smrg case PIXEL_FMT_YVYU: 301772b676d7Smrg case PIXEL_FMT_RGB6: 301872b676d7Smrg case PIXEL_FMT_RGB5: 301972b676d7Smrg default: 302072b676d7Smrg overlay.planar = 0; 302172b676d7Smrg#ifdef SISMERGED 302272b676d7Smrg if((!pSiS->MergedFB) || (overlay.DoFirst)) { 302372b676d7Smrg#endif 302472b676d7Smrg sx = (pPriv->src_x + srcOffsetX) & ~1; 302572b676d7Smrg sy = (pPriv->src_y + srcOffsetY); 302672b676d7Smrg overlay.PSY = (pPriv->bufAddr[pPriv->currentBuf] + sx*2 + sy*srcPitch); 302772b676d7Smrg overlay.PSY += FBOFFSET; 302872b676d7Smrg overlay.PSY >>= pPriv->shiftValue; 302972b676d7Smrg#ifdef SISMERGED 303072b676d7Smrg } 303172b676d7Smrg if((pSiS->MergedFB) && (overlay.DoSecond)) { 303272b676d7Smrg sx2 = (pPriv->src_x + srcOffsetX2) & ~1; 303372b676d7Smrg sy2 = (pPriv->src_y + srcOffsetY2); 303472b676d7Smrg overlay.PSY2 = (pPriv->bufAddr[pPriv->currentBuf] + sx2*2 + sy2*srcPitch); 303572b676d7Smrg overlay.PSY2 += FBOFFSET; 303672b676d7Smrg overlay.PSY2 >>= pPriv->shiftValue; 303772b676d7Smrg } 303872b676d7Smrg#endif 303972b676d7Smrg break; 304072b676d7Smrg } 304172b676d7Smrg 304272b676d7Smrg /* Some clipping checks */ 304372b676d7Smrg#ifdef SISMERGED 304472b676d7Smrg if((!pSiS->MergedFB) || (overlay.DoFirst)) { 304572b676d7Smrg#endif 304672b676d7Smrg overlay.srcW = pPriv->src_w - (sx - pPriv->src_x); 304772b676d7Smrg overlay.srcH = pPriv->src_h - (sy - pPriv->src_y); 304872b676d7Smrg if( (pPriv->oldx1 != overlay.dstBox.x1) || 304972b676d7Smrg (pPriv->oldx2 != overlay.dstBox.x2) || 305072b676d7Smrg (pPriv->oldy1 != overlay.dstBox.y1) || 305172b676d7Smrg (pPriv->oldy2 != overlay.dstBox.y2) ) { 305272b676d7Smrg pPriv->mustwait = 1; 305372b676d7Smrg pPriv->oldx1 = overlay.dstBox.x1; pPriv->oldx2 = overlay.dstBox.x2; 305472b676d7Smrg pPriv->oldy1 = overlay.dstBox.y1; pPriv->oldy2 = overlay.dstBox.y2; 305572b676d7Smrg } 305672b676d7Smrg#ifdef SISMERGED 305772b676d7Smrg } 305872b676d7Smrg if((pSiS->MergedFB) && (overlay.DoSecond)) { 305972b676d7Smrg overlay.srcW2 = pPriv->src_w - (sx2 - pPriv->src_x); 306072b676d7Smrg overlay.srcH2 = pPriv->src_h - (sy2 - pPriv->src_y); 306172b676d7Smrg if( (pPriv->oldx1_2 != overlay.dstBox2.x1) || 306272b676d7Smrg (pPriv->oldx2_2 != overlay.dstBox2.x2) || 306372b676d7Smrg (pPriv->oldy1_2 != overlay.dstBox2.y1) || 306472b676d7Smrg (pPriv->oldy2_2 != overlay.dstBox2.y2) ) { 306572b676d7Smrg pPriv->mustwait = 1; 306672b676d7Smrg pPriv->oldx1_2 = overlay.dstBox2.x1; pPriv->oldx2_2 = overlay.dstBox2.x2; 306772b676d7Smrg pPriv->oldy1_2 = overlay.dstBox2.y1; pPriv->oldy2_2 = overlay.dstBox2.y2; 306872b676d7Smrg } 306972b676d7Smrg } 307072b676d7Smrg#endif 307172b676d7Smrg 307272b676d7Smrg#ifdef SISMERGED 307372b676d7Smrg /* Disable an overlay if it is not to be displayed (but enabled currently) */ 307472b676d7Smrg if((pSiS->MergedFB) && (pPriv->hasTwoOverlays)) { 307572b676d7Smrg if(!overlay.DoFirst) { 307672b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0x05); 307772b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x01); 307872b676d7Smrg temp = getvideoreg(pSiS,Index_VI_Control_Misc0); 307972b676d7Smrg if(temp & 0x02) { 308072b676d7Smrg watchdog = WATCHDOG_DELAY; 308172b676d7Smrg while((!vblank_active_CRT1(pSiS, pPriv)) && --watchdog); 308272b676d7Smrg watchdog = WATCHDOG_DELAY; 308372b676d7Smrg while(vblank_active_CRT1(pSiS, pPriv) && --watchdog); 308472b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02); 308572b676d7Smrg } 308672b676d7Smrg } else if(!overlay.DoSecond) { 308772b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, 0x01); 308872b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x01); 308972b676d7Smrg temp = getvideoreg(pSiS,Index_VI_Control_Misc0); 309072b676d7Smrg if(temp & 0x02) { 309172b676d7Smrg watchdog = WATCHDOG_DELAY; 309272b676d7Smrg while((!vblank_active_CRT2(pSiS, pPriv)) && --watchdog); 309372b676d7Smrg watchdog = WATCHDOG_DELAY; 309472b676d7Smrg while(vblank_active_CRT2(pSiS, pPriv) && --watchdog); 309572b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02); 309672b676d7Smrg } 309772b676d7Smrg } 309872b676d7Smrg } 309972b676d7Smrg#endif 310072b676d7Smrg 310172b676d7Smrg /* Loop head */ 310272b676d7Smrg /* Note: index can only be 1 for CRT2, ie overlay 1 310372b676d7Smrg * is only used for CRT2. 310472b676d7Smrg */ 310572b676d7Smrg if(pPriv->displayMode & DISPMODE_SINGLE2) { 310672b676d7Smrg if(pPriv->hasTwoOverlays) { /* We have 2 overlays: */ 310772b676d7Smrg if(pPriv->dualHeadMode) { 310872b676d7Smrg /* Dual head: We use overlay 2 for CRT2 */ 310972b676d7Smrg index = 1; iscrt2 = 1; 311072b676d7Smrg } else { 311172b676d7Smrg /* Single head: We use overlay 1 for CRT2 */ 311272b676d7Smrg index = 0; iscrt2 = 1; 311372b676d7Smrg } 311472b676d7Smrg } else { /* We have 1 overlay */ 311572b676d7Smrg /* We use that only overlay for CRT2 */ 311672b676d7Smrg index = 0; iscrt2 = 1; 311772b676d7Smrg } 311872b676d7Smrg overlay.VBlankActiveFunc = vblank_active_CRT2; 311972b676d7Smrg#ifdef SISMERGED 312072b676d7Smrg if(!pPriv->hasTwoOverlays) { 312172b676d7Smrg if((pSiS->MergedFB) && (!overlay.DoSecond)) { 312272b676d7Smrg index = 0; iscrt2 = 0; 312372b676d7Smrg overlay.VBlankActiveFunc = vblank_active_CRT1; 312472b676d7Smrg pPriv->displayMode = DISPMODE_SINGLE1; 312572b676d7Smrg } 312672b676d7Smrg } 312772b676d7Smrg#endif 312872b676d7Smrg } else { 312972b676d7Smrg index = 0; iscrt2 = 0; 313072b676d7Smrg overlay.VBlankActiveFunc = vblank_active_CRT1; 313172b676d7Smrg#ifdef SISMERGED 313272b676d7Smrg if((pSiS->MergedFB) && (!overlay.DoFirst)) { 313372b676d7Smrg if(pPriv->hasTwoOverlays) index = 1; 313472b676d7Smrg iscrt2 = 1; 313572b676d7Smrg overlay.VBlankActiveFunc = vblank_active_CRT2; 313672b676d7Smrg if(!pPriv->hasTwoOverlays) { 313772b676d7Smrg pPriv->displayMode = DISPMODE_SINGLE2; 313872b676d7Smrg } 313972b676d7Smrg } 314072b676d7Smrg#endif 314172b676d7Smrg } 314272b676d7Smrg 314372b676d7Smrg /* set display mode SR06,32 (CRT1, CRT2 or mirror) */ 314472b676d7Smrg set_disptype_regs(pScrn, pPriv); 314572b676d7Smrg 314672b676d7Smrg /* set (not only calc) merge line buffer */ 314772b676d7Smrg#ifdef SISMERGED 314872b676d7Smrg if(!pSiS->MergedFB) { 314972b676d7Smrg#endif 315072b676d7Smrg merge_line_buf(pSiS, pPriv, (overlay.srcW > pPriv->linebufMergeLimit), overlay.srcW, 315172b676d7Smrg pPriv->linebufMergeLimit); 315272b676d7Smrg#ifdef SISMERGED 315372b676d7Smrg } else { 315472b676d7Smrg Bool temp1 = FALSE, temp2 = FALSE; 315572b676d7Smrg if(overlay.DoFirst) { 315672b676d7Smrg if(overlay.srcW > pPriv->linebufMergeLimit) temp1 = TRUE; 315772b676d7Smrg } 315872b676d7Smrg if(overlay.DoSecond) { 315972b676d7Smrg if(overlay.srcW2 > pPriv->linebufMergeLimit) temp2 = TRUE; 316072b676d7Smrg } 316172b676d7Smrg merge_line_buf_mfb(pSiS, pPriv, temp1, temp2, overlay.srcW, overlay.srcW2, 316272b676d7Smrg pPriv->linebufMergeLimit); 316372b676d7Smrg } 316472b676d7Smrg#endif 316572b676d7Smrg 316672b676d7Smrg /* calculate (not set!) line buffer length */ 316772b676d7Smrg#ifdef SISMERGED 316872b676d7Smrg if((!pSiS->MergedFB) || (overlay.DoFirst)) 316972b676d7Smrg#endif 317072b676d7Smrg calc_line_buf_size_1(&overlay, pPriv); 317172b676d7Smrg#ifdef SISMERGED 317272b676d7Smrg if((pSiS->MergedFB) && (overlay.DoSecond)) 317372b676d7Smrg calc_line_buf_size_2(&overlay, pPriv); 317472b676d7Smrg#endif 317572b676d7Smrg 317672b676d7Smrg if(pPriv->dualHeadMode) { 317772b676d7Smrg#ifdef SISDUALHEAD 317872b676d7Smrg if(!pSiS->SecondHead) { 317972b676d7Smrg if(pPriv->updatetvxpos) { 318072b676d7Smrg SiS_SetTVxposoffset(pScrn, pPriv->tvxpos); 318172b676d7Smrg pPriv->updatetvxpos = FALSE; 318272b676d7Smrg } 318372b676d7Smrg if(pPriv->updatetvypos) { 318472b676d7Smrg SiS_SetTVyposoffset(pScrn, pPriv->tvypos); 318572b676d7Smrg pPriv->updatetvypos = FALSE; 318672b676d7Smrg } 318772b676d7Smrg } 318872b676d7Smrg#endif 318972b676d7Smrg } else { 319072b676d7Smrg if(pPriv->updatetvxpos) { 319172b676d7Smrg SiS_SetTVxposoffset(pScrn, pPriv->tvxpos); 319272b676d7Smrg pPriv->updatetvxpos = FALSE; 319372b676d7Smrg } 319472b676d7Smrg if(pPriv->updatetvypos) { 319572b676d7Smrg SiS_SetTVyposoffset(pScrn, pPriv->tvypos); 319672b676d7Smrg pPriv->updatetvypos = FALSE; 319772b676d7Smrg } 319872b676d7Smrg } 319972b676d7Smrg 320072b676d7Smrg#if 0 /* Clearing this does not seem to be required */ 320172b676d7Smrg /* and might even be dangerous. */ 320272b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 320372b676d7Smrg watchdog = WATCHDOG_DELAY; 320472b676d7Smrg while(overlay.VBlankActiveFunc(pSiS, pPriv) && --watchdog); 320572b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc3, 0x00, 0x03); 320672b676d7Smrg } 320772b676d7Smrg#endif 320872b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc3, 0x03, 0x03); 320972b676d7Smrg 321072b676d7Smrg /* Do the following in a loop for CRT1 and CRT2 ----------------- */ 321172b676d7SmrgMIRROR: 321272b676d7Smrg 321372b676d7Smrg /* calculate scale factor */ 321472b676d7Smrg#ifdef SISMERGED 321572b676d7Smrg if(pSiS->MergedFB && iscrt2) 321672b676d7Smrg calc_scale_factor_2(&overlay, pScrn, pPriv, index, iscrt2); 321772b676d7Smrg else 321872b676d7Smrg#endif 321972b676d7Smrg calc_scale_factor(&overlay, pScrn, pPriv, index, iscrt2); 322072b676d7Smrg 322172b676d7Smrg /* Select overlay 0 (used for CRT1/or CRT2) or overlay 1 (used for CRT2 only) */ 322272b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc2, index, 0x01); 322372b676d7Smrg 322472b676d7Smrg /* set format (before color and chroma keys) */ 322572b676d7Smrg set_format(pSiS, &overlay); 322672b676d7Smrg 322772b676d7Smrg /* set color key */ 322872b676d7Smrg set_colorkey(pSiS, pPriv->colorKey); 322972b676d7Smrg 323072b676d7Smrg if(pPriv->usechromakey) { 323172b676d7Smrg /* Select chroma key format (300 series only) */ 323272b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA) { 323372b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc0, 323472b676d7Smrg (pPriv->yuvchromakey ? 0x40 : 0x00), 0x40); 323572b676d7Smrg } 323672b676d7Smrg set_chromakey(pSiS, pPriv->chromamin, pPriv->chromamax); 323772b676d7Smrg } 323872b676d7Smrg 323972b676d7Smrg /* set brightness, contrast, hue, saturation */ 324072b676d7Smrg set_brightness(pSiS, pPriv->brightness); 324172b676d7Smrg set_contrast(pSiS, pPriv->contrast); 324272b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 324372b676d7Smrg set_hue(pSiS, pPriv->hue); 324472b676d7Smrg set_saturation(pSiS, pPriv->saturation); 324572b676d7Smrg } 324672b676d7Smrg 324772b676d7Smrg /* enable/disable graphics display around overlay 324872b676d7Smrg * (Since disabled overlays don't get treated in this 324972b676d7Smrg * loop, we omit respective checks here) 325072b676d7Smrg */ 325172b676d7Smrg if(!iscrt2) { 325272b676d7Smrg set_disablegfx(pSiS, pPriv->disablegfx, &overlay); 325372b676d7Smrg } else if(!pSiS->hasTwoOverlays) { 325472b676d7Smrg set_disablegfx(pSiS, FALSE, &overlay); 325572b676d7Smrg } 325672b676d7Smrg set_disablegfxlr(pSiS, pPriv->disablegfxlr, &overlay); 325772b676d7Smrg 325872b676d7Smrg#ifdef SIS_CP 325972b676d7Smrg SIS_CP_VIDEO_SET_CP 326072b676d7Smrg#endif 326172b676d7Smrg 326272b676d7Smrg /* set remaining overlay parameters */ 326372b676d7Smrg set_overlay(pSiS, &overlay, pPriv, index, iscrt2); 326472b676d7Smrg 326572b676d7Smrg /* enable overlay */ 326672b676d7Smrg setvideoregmask (pSiS, Index_VI_Control_Misc0, 0x02, 0x02); 326772b676d7Smrg 326872b676d7Smrg /* loop foot */ 326972b676d7Smrg if(pPriv->displayMode & DISPMODE_MIRROR && 327072b676d7Smrg index == 0 && 327172b676d7Smrg pPriv->hasTwoOverlays) { 327272b676d7Smrg#ifdef SISMERGED 327372b676d7Smrg if((!pSiS->MergedFB) || overlay.DoSecond) { 327472b676d7Smrg#endif 327572b676d7Smrg index = 1; iscrt2 = 1; 327672b676d7Smrg overlay.VBlankActiveFunc = vblank_active_CRT2; 327772b676d7Smrg goto MIRROR; 327872b676d7Smrg#ifdef SISMERGED 327972b676d7Smrg } 328072b676d7Smrg#endif 328172b676d7Smrg } 328272b676d7Smrg 328372b676d7Smrg /* Now for the trigger: This is a bad hack to work-around 328472b676d7Smrg * an obvious hardware bug: Overlay 1 (which is ONLY used 328572b676d7Smrg * for CRT2 in this driver) does not always update its 328672b676d7Smrg * window position and some other stuff. Earlier, this was 328772b676d7Smrg * solved be disabling the overlay, but this took forever 328872b676d7Smrg * and was ugly on the screen. 328972b676d7Smrg * Now: We write 0x03 to 0x74 from the beginning. This is 329072b676d7Smrg * meant as a "lock" - the driver is supposed to write 0 329172b676d7Smrg * to this register, bit 0 for overlay 0, bit 1 for over- 329272b676d7Smrg * lay 1, then change buffer addresses, pitches, window 329372b676d7Smrg * position, scaler registers, format, etc., then write 329472b676d7Smrg * 1 to 0x74. The hardware then reads the registers into 329572b676d7Smrg * its internal engine and clears these bits. 329672b676d7Smrg * All this works for overlay 0, but not 1. Overlay 1 329772b676d7Smrg * has assumingly the following restrictions: 329872b676d7Smrg * - New data written to the registers is only read 329972b676d7Smrg * correctly by the engine if the registers are written 330072b676d7Smrg * when the current scanline is beyond the current 330172b676d7Smrg * overlay position and below the maximum visible 330272b676d7Smrg * scanline (vertical screen resolution) 330372b676d7Smrg * - If a vertical retrace occures during writing the 330472b676d7Smrg * registers, the registers written BEFORE this re- 330572b676d7Smrg * trace happened, are not being read into the 330672b676d7Smrg * engine if the trigger is set after the retrace. 330772b676d7Smrg * Therefore: We write the overlay registers above in 330872b676d7Smrg * set_overlay only if the scanline matches, and save 330972b676d7Smrg * the then current scanline. If this scanline is higher 331072b676d7Smrg * than the now current scanline, we assume a retrace, 331172b676d7Smrg * wait for the scanline to match the criteria above again, 331272b676d7Smrg * and rewrite all relevant registers. 331372b676d7Smrg * I have no idea if this is meant that way, but after 331472b676d7Smrg * fiddling three entire days with this crap, I found this 331572b676d7Smrg * to be the only solution. 331672b676d7Smrg */ 331772b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 331872b676d7Smrg if((pPriv->mustwait) && index) { 331972b676d7Smrg watchdog = get_scanline_CRT2(pSiS, pPriv); 332072b676d7Smrg if(watchdog <= overlay.oldLine) { 332172b676d7Smrg int i, mytop = overlay.oldtop; 332272b676d7Smrg int screenHeight = overlay.SCREENheight; 332372b676d7Smrg#ifdef SISMERGED 332472b676d7Smrg if(pSiS->MergedFB) { 332572b676d7Smrg screenHeight = overlay.SCREENheight2; 332672b676d7Smrg } 332772b676d7Smrg#endif 332872b676d7Smrg if(mytop < screenHeight - 2) { 332972b676d7Smrg do { 333072b676d7Smrg watchdog = get_scanline_CRT2(pSiS, pPriv); 333172b676d7Smrg } while((watchdog <= mytop) || (watchdog >= screenHeight)); 333272b676d7Smrg } 333372b676d7Smrg for(i=0x02; i<=0x12; i++) { 333472b676d7Smrg setvideoreg(pSiS, i, getvideoreg(pSiS, i)); 333572b676d7Smrg } 333672b676d7Smrg for(i=0x18; i<=0x1c; i++) { 333772b676d7Smrg setvideoreg(pSiS, i, getvideoreg(pSiS, i)); 333872b676d7Smrg } 333972b676d7Smrg for(i=0x2c; i<=0x2e; i++) { 334072b676d7Smrg setvideoreg(pSiS, i, getvideoreg(pSiS, i)); 334172b676d7Smrg } 334272b676d7Smrg for(i=0x6b; i<=0x6f; i++) { 334372b676d7Smrg setvideoreg(pSiS, i, getvideoreg(pSiS, i)); 334472b676d7Smrg } 334572b676d7Smrg } 334672b676d7Smrg } 334772b676d7Smrg /* Trigger register copy for 315/330 series */ 334872b676d7Smrg setvideoregmask(pSiS, Index_VI_Control_Misc3, 0x03, 0x03); 334972b676d7Smrg } 335072b676d7Smrg 335172b676d7Smrg pPriv->mustwait = 0; 335272b676d7Smrg pPriv->overlayStatus = TRUE; 335372b676d7Smrg} 335472b676d7Smrg 335572b676d7Smrg/********************************* 335672b676d7Smrg * Memory management * 335772b676d7Smrg *********************************/ 335872b676d7Smrg 335972b676d7Smrg#ifdef SIS_USE_EXA 336072b676d7Smrgstatic void 336172b676d7SmrgSiSDestroyArea(ScreenPtr pScreen, ExaOffscreenArea *area) 336272b676d7Smrg{ 336372b676d7Smrg void **handle = (void *)area->privData; 336472b676d7Smrg *handle = NULL; 336572b676d7Smrg} 336672b676d7Smrg#endif 336772b676d7Smrg 336872b676d7Smrgunsigned int 336972b676d7SmrgSISAllocateFBMemory( 337072b676d7Smrg ScrnInfoPtr pScrn, 337172b676d7Smrg void **handle, 337272b676d7Smrg int bytesize 337372b676d7Smrg){ 337472b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 337574c14cd6Smrg ScreenPtr pScreen = xf86ScrnToScreen(pScrn); 337672b676d7Smrg 337772b676d7Smrg#ifdef SIS_USE_XAA 337872b676d7Smrg if(!pSiS->useEXA) { 337972b676d7Smrg FBLinearPtr linear = (FBLinearPtr)(*handle); 338072b676d7Smrg FBLinearPtr new_linear; 338172b676d7Smrg int depth = pSiS->CurrentLayout.bitsPerPixel >> 3; 338272b676d7Smrg int size = ((bytesize + depth - 1) / depth); 338372b676d7Smrg 338472b676d7Smrg if(linear) { 338572b676d7Smrg if(linear->size >= size) { 338672b676d7Smrg return (unsigned int)(linear->offset * depth); 338772b676d7Smrg } 338872b676d7Smrg 338972b676d7Smrg if(xf86ResizeOffscreenLinear(linear, size)) { 339072b676d7Smrg return (unsigned int)(linear->offset * depth); 339172b676d7Smrg } 339272b676d7Smrg 339372b676d7Smrg xf86FreeOffscreenLinear(linear); 339472b676d7Smrg *handle = NULL; 339572b676d7Smrg } 339672b676d7Smrg 339772b676d7Smrg new_linear = xf86AllocateOffscreenLinear(pScreen, size, 8, NULL, NULL, NULL); 339872b676d7Smrg 339972b676d7Smrg if(!new_linear) { 340072b676d7Smrg int max_size; 340172b676d7Smrg 340272b676d7Smrg xf86QueryLargestOffscreenLinear(pScreen, &max_size, 8, PRIORITY_EXTREME); 340372b676d7Smrg 340472b676d7Smrg if(max_size < size) 340572b676d7Smrg return 0; 340672b676d7Smrg 340772b676d7Smrg xf86PurgeUnlockedOffscreenAreas(pScreen); 340872b676d7Smrg new_linear = xf86AllocateOffscreenLinear(pScreen, size, 8, NULL, NULL, NULL); 340972b676d7Smrg } 341072b676d7Smrg if(!new_linear) { 341172b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 341272b676d7Smrg "Xv: Failed to allocate %d pixels of linear video memory\n", size); 341372b676d7Smrg return 0; 341472b676d7Smrg } else { 341572b676d7Smrg *handle = (void *)new_linear; 341672b676d7Smrg return (unsigned int)(new_linear->offset * depth); 341772b676d7Smrg } 341872b676d7Smrg } 341972b676d7Smrg#endif 342072b676d7Smrg#ifdef SIS_USE_EXA 342172b676d7Smrg if(pSiS->useEXA && !pSiS->NoAccel) { 342272b676d7Smrg ExaOffscreenArea *area = (ExaOffscreenArea *)(*handle); 342372b676d7Smrg 342472b676d7Smrg if(area) { 342572b676d7Smrg if(area->size >= bytesize) return (unsigned int)(area->offset); 342672b676d7Smrg 342772b676d7Smrg exaOffscreenFree(pScreen, area); 342872b676d7Smrg *handle = NULL; 342972b676d7Smrg } 343072b676d7Smrg 343172b676d7Smrg if(!(area = exaOffscreenAlloc(pScreen, bytesize, 8, TRUE, SiSDestroyArea, (pointer)handle))) { 343272b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 343372b676d7Smrg "Xv: Failed to allocate %d bytes of video memory\n", bytesize); 343472b676d7Smrg return 0; 343572b676d7Smrg } else { 343672b676d7Smrg *handle = (void *)area; 343772b676d7Smrg return (unsigned int)(area->offset); 343872b676d7Smrg } 343972b676d7Smrg } 344072b676d7Smrg#endif 344172b676d7Smrg 344272b676d7Smrg return 0; 344372b676d7Smrg} 344472b676d7Smrg 344572b676d7Smrgvoid 344672b676d7SmrgSISFreeFBMemory(ScrnInfoPtr pScrn, void **handle) 344772b676d7Smrg{ 344872b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 344972b676d7Smrg#ifdef SIS_USE_EXA 345074c14cd6Smrg ScreenPtr pScreen = xf86ScrnToScreen(pScrn); 345172b676d7Smrg#endif 345272b676d7Smrg 345372b676d7Smrg#ifdef SIS_USE_XAA 345472b676d7Smrg if(!pSiS->useEXA) { 345572b676d7Smrg if(*handle) { 345672b676d7Smrg xf86FreeOffscreenLinear((FBLinearPtr)(*handle)); 345772b676d7Smrg } 345872b676d7Smrg } 345972b676d7Smrg#endif 346072b676d7Smrg#ifdef SIS_USE_EXA 346172b676d7Smrg if(pSiS->useEXA && !pSiS->NoAccel) { 346272b676d7Smrg if(*handle) { 346372b676d7Smrg exaOffscreenFree(pScreen, (ExaOffscreenArea *)(*handle)); 346472b676d7Smrg } 346572b676d7Smrg } 346672b676d7Smrg#endif 346772b676d7Smrg *handle = NULL; 346872b676d7Smrg} 346972b676d7Smrg 347072b676d7Smrg/********************************* 347172b676d7Smrg * StopVideo() * 347272b676d7Smrg *********************************/ 347372b676d7Smrg 347472b676d7Smrgstatic void 347572b676d7SmrgSISStopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown) 347672b676d7Smrg{ 347772b676d7Smrg SISPortPrivPtr pPriv = (SISPortPrivPtr)data; 347872b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 347972b676d7Smrg 348072b676d7Smrg if(pPriv->grabbedByV4L) return; 348172b676d7Smrg 348272b676d7Smrg REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 348372b676d7Smrg 348472b676d7Smrg if(shutdown) { 348572b676d7Smrg if(pPriv->videoStatus & CLIENT_VIDEO_ON) { 348672b676d7Smrg close_overlay(pSiS, pPriv); 348772b676d7Smrg pPriv->mustwait = 1; 348872b676d7Smrg } 348972b676d7Smrg SISFreeFBMemory(pScrn, &pPriv->handle); 349072b676d7Smrg pPriv->videoStatus = 0; 349172b676d7Smrg } else { 349272b676d7Smrg if(pPriv->videoStatus & CLIENT_VIDEO_ON) { 349372b676d7Smrg UpdateCurrentTime(); 349472b676d7Smrg pPriv->offTime = currentTime.milliseconds + OFF_DELAY; 349572b676d7Smrg pPriv->videoStatus = OFF_TIMER | CLIENT_VIDEO_ON; 349672b676d7Smrg pSiS->VideoTimerCallback = SISVideoTimerCallback; 349772b676d7Smrg } 349872b676d7Smrg } 349972b676d7Smrg} 350072b676d7Smrg 350172b676d7Smrg/********************************* 350272b676d7Smrg * PutImage() * 350372b676d7Smrg *********************************/ 350472b676d7Smrg 350572b676d7Smrgstatic int 350672b676d7SmrgSISPutImage( 350772b676d7Smrg ScrnInfoPtr pScrn, 350872b676d7Smrg short src_x, short src_y, 350972b676d7Smrg short drw_x, short drw_y, 351072b676d7Smrg short src_w, short src_h, 351172b676d7Smrg short drw_w, short drw_h, 351272b676d7Smrg int id, UChar *buf, 351372b676d7Smrg short width, short height, 351472b676d7Smrg Bool sync, 351572b676d7Smrg RegionPtr clipBoxes, pointer data, 351672b676d7Smrg DrawablePtr pDraw 351772b676d7Smrg){ 351872b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 351972b676d7Smrg SISPortPrivPtr pPriv = (SISPortPrivPtr)data; 352072b676d7Smrg#ifdef SIS_USE_XAA 352172b676d7Smrg XAAInfoRecPtr pXAA = pSiS->AccelInfoPtr; 352272b676d7Smrg int depth = pSiS->CurrentLayout.bitsPerPixel >> 3; 352372b676d7Smrg int myreds[] = { 0x000000ff, 0x0000f800, 0, 0x00ff0000 }; 352472b676d7Smrg#endif 352572b676d7Smrg int totalSize = 0; 352672b676d7Smrg#ifdef SISDEINT 352772b676d7Smrg Bool deintfm = (pPriv->deinterlacemethod > 1) ? TRUE : FALSE; 352872b676d7Smrg#endif 352972b676d7Smrg 353072b676d7Smrg#if 0 353172b676d7Smrg xf86DrvMsg(0, X_INFO, "PutImage: src %dx%d-%dx%d, drw %dx%d-%dx%d, id %x, w %d h %d, buf %p\n", 353272b676d7Smrg src_x, src_y, src_w, src_h, drw_x, drw_y, drw_w, drw_h, id, width, height, buf); 353372b676d7Smrg#endif 353472b676d7Smrg 353572b676d7Smrg if(pPriv->grabbedByV4L) return Success; 353672b676d7Smrg 353772b676d7Smrg pPriv->drw_x = drw_x; 353872b676d7Smrg pPriv->drw_y = drw_y; 353972b676d7Smrg pPriv->drw_w = drw_w; 354072b676d7Smrg pPriv->drw_h = drw_h; 354172b676d7Smrg pPriv->src_x = src_x; 354272b676d7Smrg pPriv->src_y = src_y; 354372b676d7Smrg pPriv->src_w = src_w; 354472b676d7Smrg pPriv->src_h = src_h; 354572b676d7Smrg pPriv->id = id; 354672b676d7Smrg pPriv->height = height; 354772b676d7Smrg 354872b676d7Smrg /* Pixel formats: 354972b676d7Smrg 1. YU12: 3 planes: H V 355072b676d7Smrg Y sample period 1 1 (8 bit per pixel) 355172b676d7Smrg V sample period 2 2 (8 bit per pixel, subsampled) 355272b676d7Smrg U sample period 2 2 (8 bit per pixel, subsampled) 355372b676d7Smrg 355472b676d7Smrg Y plane is fully sampled (width*height), U and V planes 355572b676d7Smrg are sampled in 2x2 blocks, hence a group of 4 pixels requires 355672b676d7Smrg 4 + 1 + 1 = 6 bytes. The data is planar, ie in single planes 355772b676d7Smrg for Y, U and V. 355872b676d7Smrg 2. UYVY: 3 planes: H V 355972b676d7Smrg Y sample period 1 1 (8 bit per pixel) 356072b676d7Smrg V sample period 2 1 (8 bit per pixel, subsampled) 356172b676d7Smrg U sample period 2 1 (8 bit per pixel, subsampled) 356272b676d7Smrg Y plane is fully sampled (width*height), U and V planes 356372b676d7Smrg are sampled in 2x1 blocks, hence a group of 4 pixels requires 356472b676d7Smrg 4 + 2 + 2 = 8 bytes. The data is bit packed, there are no separate 356572b676d7Smrg Y, U or V planes. 356672b676d7Smrg Bit order: U0 Y0 V0 Y1 U2 Y2 V2 Y3 ... 356772b676d7Smrg 3. I420: Like YU12, but planes U and V are in reverse order. 356872b676d7Smrg 4. YUY2: Like UYVY, but order is 356972b676d7Smrg Y0 U0 Y1 V0 Y2 U2 Y3 V2 ... 357072b676d7Smrg 5. YVYU: Like YUY2, but order is 357172b676d7Smrg Y0 V0 Y1 U0 Y2 V2 Y3 U2 ... 357272b676d7Smrg 6. NV12, NV21: 2 planes H V 357372b676d7Smrg Y sample period 1 1 (8 bit per pixel) 357472b676d7Smrg V sample period 2 1 (8 bit per pixel, subsampled) 357572b676d7Smrg U sample period 2 1 (8 bit per pixel, subsampled) 357672b676d7Smrg Y plane is fully samples (width*height), U and V planes are 357772b676d7Smrg interleaved in memory (one byte U, one byte V for NV12, NV21 357872b676d7Smrg other way round) and sampled in 2x1 blocks. Otherwise such 357972b676d7Smrg as all other planar formats. 358072b676d7Smrg */ 358172b676d7Smrg 358272b676d7Smrg switch(id){ 358372b676d7Smrg case PIXEL_FMT_YV12: 358472b676d7Smrg case PIXEL_FMT_I420: 358572b676d7Smrg case PIXEL_FMT_NV12: 358672b676d7Smrg case PIXEL_FMT_NV21: 358772b676d7Smrg pPriv->srcPitch = (width + 7) & ~7; 358872b676d7Smrg /* Size = width * height * 3 / 2 */ 358972b676d7Smrg totalSize = (pPriv->srcPitch * height * 3) >> 1; /* Verified */ 359072b676d7Smrg break; 359172b676d7Smrg case PIXEL_FMT_YUY2: 359272b676d7Smrg case PIXEL_FMT_UYVY: 359372b676d7Smrg case PIXEL_FMT_YVYU: 359472b676d7Smrg case PIXEL_FMT_RGB6: 359572b676d7Smrg case PIXEL_FMT_RGB5: 359672b676d7Smrg default: 359772b676d7Smrg pPriv->srcPitch = ((width << 1) + 3) & ~3; /* Verified */ 359872b676d7Smrg /* Size = width * 2 * height */ 359972b676d7Smrg totalSize = pPriv->srcPitch * height; 360072b676d7Smrg } 360172b676d7Smrg 360272b676d7Smrg /* make it a multiple of 16 to simplify to copy loop */ 360372b676d7Smrg totalSize += 15; 360472b676d7Smrg totalSize &= ~15; /* in bytes */ 360572b676d7Smrg 360672b676d7Smrg /* allocate memory (we do doublebuffering) - size is in bytes */ 360772b676d7Smrg if(!(pPriv->bufAddr[0] = SISAllocateFBMemory(pScrn, &pPriv->handle, totalSize << 1))) 360872b676d7Smrg return BadAlloc; 360972b676d7Smrg 361072b676d7Smrg#ifdef SISDEINT 361172b676d7Smrg if(deintfm) { 361272b676d7Smrg pPriv->bufAddr[1] = pPriv->bufAddr[0] + pPriv->srcPitch; 361372b676d7Smrg 361472b676d7Smrg { 361572b676d7Smrg CARD8 *src = (CARD8 *)buf; 361672b676d7Smrg CARD8 *dest = (CARD8 *)(pSiS->FbBase + pPriv->bufAddr[pPriv->currentBuf]); 361772b676d7Smrg int i = height; 361872b676d7Smrg while(i--) { 361972b676d7Smrg SiSMemCopyToVideoRam(pSiS, dest, src, pPriv->srcPitch); 362072b676d7Smrg src += pPriv->srcPitch; 362172b676d7Smrg dest += (pPriv->srcPitch << 1); 362272b676d7Smrg } 362372b676d7Smrg } 362472b676d7Smrg 362572b676d7Smrg } else { 362672b676d7Smrg#endif 362772b676d7Smrg pPriv->bufAddr[1] = pPriv->bufAddr[0] + totalSize; 362872b676d7Smrg 362972b676d7Smrg /* copy data */ 363072b676d7Smrg if((pSiS->XvUseMemcpy) || (totalSize < 16)) { 363172b676d7Smrg SiSMemCopyToVideoRam(pSiS, pSiS->FbBase + pPriv->bufAddr[pPriv->currentBuf], buf, totalSize); 363272b676d7Smrg } else { 363372b676d7Smrg ULong i; 363472b676d7Smrg CARD32 *src = (CARD32 *)buf; 363572b676d7Smrg CARD32 *dest = (CARD32 *)(pSiS->FbBase + pPriv->bufAddr[pPriv->currentBuf]); 363672b676d7Smrg for(i = 0; i < (totalSize/16); i++) { 363772b676d7Smrg *dest++ = *src++; 363872b676d7Smrg *dest++ = *src++; 363972b676d7Smrg *dest++ = *src++; 364072b676d7Smrg *dest++ = *src++; 364172b676d7Smrg } 364272b676d7Smrg } 364372b676d7Smrg#ifdef SISDEINT 364472b676d7Smrg } 364572b676d7Smrg#endif 364672b676d7Smrg 364772b676d7Smrg SISDisplayVideo(pScrn, pPriv); 364872b676d7Smrg 364972b676d7Smrg /* update cliplist */ 365072b676d7Smrg if(pPriv->autopaintColorKey && 365172b676d7Smrg (pPriv->grabbedByV4L || 365272b676d7Smrg#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,3,99,3,0) 365372b676d7Smrg (!RegionsEqual(&pPriv->clip, clipBoxes)) || 365472b676d7Smrg#else 365572b676d7Smrg (!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) || 365672b676d7Smrg#endif 365772b676d7Smrg (pPriv->PrevOverlay != pPriv->NoOverlay))) { 365872b676d7Smrg /* We always paint the colorkey for V4L */ 365972b676d7Smrg if(!pPriv->grabbedByV4L) { 366072b676d7Smrg REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes); 366172b676d7Smrg } 366272b676d7Smrg /* draw these */ 366372b676d7Smrg pPriv->PrevOverlay = pPriv->NoOverlay; 366472b676d7Smrg#ifdef SIS_USE_XAA 366572b676d7Smrg if((pPriv->NoOverlay) && pXAA && pXAA->FillMono8x8PatternRects) { 366672b676d7Smrg (*pXAA->FillMono8x8PatternRects)(pScrn, myreds[depth-1], 366772b676d7Smrg 0x000000, GXcopy, ~0, 366872b676d7Smrg REGION_NUM_RECTS(clipBoxes), 366972b676d7Smrg REGION_RECTS(clipBoxes), 367072b676d7Smrg 0x00422418, 0x18244200, 0, 0); 367172b676d7Smrg } else { 367272b676d7Smrg#endif 367372b676d7Smrg if(!pSiS->disablecolorkeycurrent) { 367472b676d7Smrg#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,1,99,1,0) 367572b676d7Smrg (*pXAA->FillSolidRects)(pScrn, pPriv->colorKey, GXcopy, ~0, 367672b676d7Smrg REGION_NUM_RECTS(clipBoxes), 367772b676d7Smrg REGION_RECTS(clipBoxes)); 367872b676d7Smrg#else 367972b676d7Smrg xf86XVFillKeyHelper(pScrn->pScreen, (pPriv->NoOverlay) ? 0x00ff0000 : pPriv->colorKey, clipBoxes); 368072b676d7Smrg#endif 368172b676d7Smrg } 368272b676d7Smrg#ifdef SIS_USE_XAA 368372b676d7Smrg } 368472b676d7Smrg#endif 368572b676d7Smrg 368672b676d7Smrg } 368772b676d7Smrg 368872b676d7Smrg pPriv->currentBuf ^= 1; 368972b676d7Smrg 369072b676d7Smrg pPriv->videoStatus = CLIENT_VIDEO_ON; 369172b676d7Smrg 369272b676d7Smrg pSiS->VideoTimerCallback = SISVideoTimerCallback; 369372b676d7Smrg 369472b676d7Smrg return Success; 369572b676d7Smrg} 369672b676d7Smrg 369772b676d7Smrg/********************************* 369872b676d7Smrg * QueryImageAttributes() * 369972b676d7Smrg *********************************/ 370072b676d7Smrg 370172b676d7Smrgstatic int 370272b676d7SmrgSISQueryImageAttributes( 370372b676d7Smrg ScrnInfoPtr pScrn, 370472b676d7Smrg int id, 370572b676d7Smrg UShort *w, UShort *h, 370672b676d7Smrg int *pitches, int *offsets 370772b676d7Smrg){ 370872b676d7Smrg int pitchY, pitchUV; 370972b676d7Smrg int size, sizeY, sizeUV; 371072b676d7Smrg 371172b676d7Smrg if(*w < IMAGE_MIN_WIDTH) *w = IMAGE_MIN_WIDTH; 371272b676d7Smrg if(*h < IMAGE_MIN_HEIGHT) *h = IMAGE_MIN_HEIGHT; 371372b676d7Smrg 371472b676d7Smrg if(*w > DummyEncoding.width) *w = DummyEncoding.width; 371572b676d7Smrg if(*h > DummyEncoding.height) *h = DummyEncoding.height; 371672b676d7Smrg 371772b676d7Smrg switch(id) { 371872b676d7Smrg case PIXEL_FMT_YV12: 371972b676d7Smrg case PIXEL_FMT_I420: 372072b676d7Smrg *w = (*w + 7) & ~7; 372172b676d7Smrg *h = (*h + 1) & ~1; 372272b676d7Smrg pitchY = *w; 372372b676d7Smrg pitchUV = *w >> 1; 372472b676d7Smrg if(pitches) { 372572b676d7Smrg pitches[0] = pitchY; 372672b676d7Smrg pitches[1] = pitches[2] = pitchUV; 372772b676d7Smrg } 372872b676d7Smrg sizeY = pitchY * (*h); 372972b676d7Smrg sizeUV = pitchUV * ((*h) >> 1); 373072b676d7Smrg if(offsets) { 373172b676d7Smrg offsets[0] = 0; 373272b676d7Smrg offsets[1] = sizeY; 373372b676d7Smrg offsets[2] = sizeY + sizeUV; 373472b676d7Smrg } 373572b676d7Smrg size = sizeY + (sizeUV << 1); 373672b676d7Smrg break; 373772b676d7Smrg case PIXEL_FMT_NV12: 373872b676d7Smrg case PIXEL_FMT_NV21: 373972b676d7Smrg *w = (*w + 7) & ~7; 374072b676d7Smrg *h = (*h + 1) & ~1; 374172b676d7Smrg pitchY = *w; 374272b676d7Smrg pitchUV = *w; 374372b676d7Smrg if(pitches) { 374472b676d7Smrg pitches[0] = pitchY; 374572b676d7Smrg pitches[1] = pitchUV; 374672b676d7Smrg } 374772b676d7Smrg sizeY = pitchY * (*h); 374872b676d7Smrg sizeUV = pitchUV * ((*h) >> 1); 374972b676d7Smrg if(offsets) { 375072b676d7Smrg offsets[0] = 0; 375172b676d7Smrg offsets[1] = sizeY; 375272b676d7Smrg } 375372b676d7Smrg size = sizeY + (sizeUV << 1); 375472b676d7Smrg break; 375572b676d7Smrg case PIXEL_FMT_YUY2: 375672b676d7Smrg case PIXEL_FMT_UYVY: 375772b676d7Smrg case PIXEL_FMT_YVYU: 375872b676d7Smrg case PIXEL_FMT_RGB6: 375972b676d7Smrg case PIXEL_FMT_RGB5: 376072b676d7Smrg default: 376172b676d7Smrg *w = (*w + 1) & ~1; 376272b676d7Smrg pitchY = *w << 1; 376372b676d7Smrg if(pitches) pitches[0] = pitchY; 376472b676d7Smrg if(offsets) offsets[0] = 0; 376572b676d7Smrg size = pitchY * (*h); 376672b676d7Smrg break; 376772b676d7Smrg } 376872b676d7Smrg 376972b676d7Smrg return size; 377072b676d7Smrg} 377172b676d7Smrg 377272b676d7Smrg 377372b676d7Smrg/********************************* 377472b676d7Smrg * OFFSCREEN SURFACES * 377572b676d7Smrg *********************************/ 377672b676d7Smrg 377772b676d7Smrgstatic int 377872b676d7SmrgSISAllocSurface ( 377972b676d7Smrg ScrnInfoPtr pScrn, 378072b676d7Smrg int id, 378172b676d7Smrg UShort w, 378272b676d7Smrg UShort h, 378372b676d7Smrg XF86SurfacePtr surface 378472b676d7Smrg) 378572b676d7Smrg{ 378672b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 378772b676d7Smrg SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn); 378872b676d7Smrg int size; 378972b676d7Smrg 379072b676d7Smrg if((w < IMAGE_MIN_WIDTH) || (h < IMAGE_MIN_HEIGHT)) 379172b676d7Smrg return BadValue; 379272b676d7Smrg 379372b676d7Smrg if((w > DummyEncoding.width) || (h > DummyEncoding.height)) 379472b676d7Smrg return BadValue; 379572b676d7Smrg 379672b676d7Smrg if(pPriv->grabbedByV4L) 379772b676d7Smrg return BadAlloc; 379872b676d7Smrg 379972b676d7Smrg w = (w + 1) & ~1; 380072b676d7Smrg pPriv->pitch = ((w << 1) + 63) & ~63; /* Only packed pixel modes supported */ 380172b676d7Smrg size = h * pPriv->pitch; 380272b676d7Smrg if(!(pPriv->offset = SISAllocateFBMemory(pScrn, &pPriv->handle, size))) 380372b676d7Smrg return BadAlloc; 380472b676d7Smrg 380572b676d7Smrg surface->width = w; 380672b676d7Smrg surface->height = h; 380772b676d7Smrg surface->pScrn = pScrn; 380872b676d7Smrg surface->id = id; 380972b676d7Smrg surface->pitches = &pPriv->pitch; 381072b676d7Smrg surface->offsets = &pPriv->offset; 381172b676d7Smrg surface->devPrivate.ptr = (pointer)pPriv; 381272b676d7Smrg 381372b676d7Smrg close_overlay(pSiS, pPriv); 381472b676d7Smrg pPriv->videoStatus = 0; 381572b676d7Smrg REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 381672b676d7Smrg pSiS->VideoTimerCallback = NULL; 381772b676d7Smrg pPriv->grabbedByV4L = TRUE; 381872b676d7Smrg return Success; 381972b676d7Smrg} 382072b676d7Smrg 382172b676d7Smrgstatic int 382272b676d7SmrgSISStopSurface (XF86SurfacePtr surface) 382372b676d7Smrg{ 382472b676d7Smrg SISPortPrivPtr pPriv = (SISPortPrivPtr)(surface->devPrivate.ptr); 382572b676d7Smrg SISPtr pSiS = SISPTR(surface->pScrn); 382672b676d7Smrg 382772b676d7Smrg if(pPriv->grabbedByV4L && pPriv->videoStatus) { 382872b676d7Smrg close_overlay(pSiS, pPriv); 382972b676d7Smrg pPriv->mustwait = 1; 383072b676d7Smrg pPriv->videoStatus = 0; 383172b676d7Smrg } 383272b676d7Smrg return Success; 383372b676d7Smrg} 383472b676d7Smrg 383572b676d7Smrgstatic int 383672b676d7SmrgSISFreeSurface (XF86SurfacePtr surface) 383772b676d7Smrg{ 383872b676d7Smrg SISPortPrivPtr pPriv = (SISPortPrivPtr)(surface->devPrivate.ptr); 383972b676d7Smrg 384072b676d7Smrg if(pPriv->grabbedByV4L) { 384172b676d7Smrg SISStopSurface(surface); 384272b676d7Smrg SISFreeFBMemory(surface->pScrn, &pPriv->handle); 384372b676d7Smrg pPriv->grabbedByV4L = FALSE; 384472b676d7Smrg } 384572b676d7Smrg return Success; 384672b676d7Smrg} 384772b676d7Smrg 384872b676d7Smrgstatic int 384972b676d7SmrgSISGetSurfaceAttribute ( 385072b676d7Smrg ScrnInfoPtr pScrn, 385172b676d7Smrg Atom attribute, 385272b676d7Smrg INT32 *value 385372b676d7Smrg) 385472b676d7Smrg{ 385572b676d7Smrg SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn); 385672b676d7Smrg 385772b676d7Smrg return SISGetPortAttribute(pScrn, attribute, value, (pointer)pPriv); 385872b676d7Smrg} 385972b676d7Smrg 386072b676d7Smrgstatic int 386172b676d7SmrgSISSetSurfaceAttribute( 386272b676d7Smrg ScrnInfoPtr pScrn, 386372b676d7Smrg Atom attribute, 386472b676d7Smrg INT32 value 386572b676d7Smrg) 386672b676d7Smrg{ 386772b676d7Smrg SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);; 386872b676d7Smrg 386972b676d7Smrg return SISSetPortAttribute(pScrn, attribute, value, (pointer)pPriv); 387072b676d7Smrg} 387172b676d7Smrg 387272b676d7Smrgstatic int 387372b676d7SmrgSISDisplaySurface ( 387472b676d7Smrg XF86SurfacePtr surface, 387572b676d7Smrg short src_x, short src_y, 387672b676d7Smrg short drw_x, short drw_y, 387772b676d7Smrg short src_w, short src_h, 387872b676d7Smrg short drw_w, short drw_h, 387972b676d7Smrg RegionPtr clipBoxes 388072b676d7Smrg) 388172b676d7Smrg{ 388272b676d7Smrg ScrnInfoPtr pScrn = surface->pScrn; 388372b676d7Smrg SISPortPrivPtr pPriv = (SISPortPrivPtr)(surface->devPrivate.ptr); 388472b676d7Smrg#ifdef SIS_USE_XAA 388572b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 388672b676d7Smrg int myreds[] = { 0x000000ff, 0x0000f800, 0, 0x00ff0000 }; 388772b676d7Smrg#endif 388872b676d7Smrg 388972b676d7Smrg if(!pPriv->grabbedByV4L) return Success; 389072b676d7Smrg 389172b676d7Smrg pPriv->drw_x = drw_x; 389272b676d7Smrg pPriv->drw_y = drw_y; 389372b676d7Smrg pPriv->drw_w = drw_w; 389472b676d7Smrg pPriv->drw_h = drw_h; 389572b676d7Smrg pPriv->src_x = src_x; 389672b676d7Smrg pPriv->src_y = src_y; 389772b676d7Smrg pPriv->src_w = src_w; 389872b676d7Smrg pPriv->src_h = src_h; 389972b676d7Smrg pPriv->id = surface->id; 390072b676d7Smrg pPriv->height = surface->height; 390172b676d7Smrg pPriv->bufAddr[0] = surface->offsets[0]; 390272b676d7Smrg pPriv->currentBuf = 0; 390372b676d7Smrg pPriv->srcPitch = surface->pitches[0]; 390472b676d7Smrg 390572b676d7Smrg SISDisplayVideo(pScrn, pPriv); 390672b676d7Smrg 390772b676d7Smrg if(pPriv->autopaintColorKey) { 390872b676d7Smrg#ifdef SIS_USE_XAA 390972b676d7Smrg XAAInfoRecPtr pXAA = pSiS->AccelInfoPtr; 391072b676d7Smrg 391172b676d7Smrg if((pPriv->NoOverlay) && pXAA && pXAA->FillMono8x8PatternRects) { 391272b676d7Smrg (*pXAA->FillMono8x8PatternRects)(pScrn, 391372b676d7Smrg myreds[(pSiS->CurrentLayout.bitsPerPixel >> 3) - 1], 391472b676d7Smrg 0x000000, GXcopy, ~0, 391572b676d7Smrg REGION_NUM_RECTS(clipBoxes), 391672b676d7Smrg REGION_RECTS(clipBoxes), 391772b676d7Smrg 0x00422418, 0x18244200, 0, 0); 391872b676d7Smrg 391972b676d7Smrg } else { 392072b676d7Smrg#endif 392172b676d7Smrg#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,1,99,1,0) 392272b676d7Smrg (*pXAA->FillSolidRects)(pScrn, pPriv->colorKey, GXcopy, ~0, 392372b676d7Smrg REGION_NUM_RECTS(clipBoxes), 392472b676d7Smrg REGION_RECTS(clipBoxes)); 392572b676d7Smrg#else 392672b676d7Smrg xf86XVFillKeyHelper(pScrn->pScreen, (pPriv->NoOverlay) ? 0x00ff0000 : pPriv->colorKey, clipBoxes); 392772b676d7Smrg#endif 392872b676d7Smrg#ifdef SIS_USE_XAA 392972b676d7Smrg } 393072b676d7Smrg#endif 393172b676d7Smrg } 393272b676d7Smrg 393372b676d7Smrg pPriv->videoStatus = CLIENT_VIDEO_ON; 393472b676d7Smrg 393572b676d7Smrg return Success; 393672b676d7Smrg} 393772b676d7Smrg 393872b676d7Smrg#define NUMOFFSCRIMAGES_300 4 393972b676d7Smrg#define NUMOFFSCRIMAGES_315 5 394072b676d7Smrg 394172b676d7Smrgstatic XF86OffscreenImageRec SISOffscreenImages[NUMOFFSCRIMAGES_315] = 394272b676d7Smrg{ 394372b676d7Smrg { 394472b676d7Smrg &SISImages[0], /* YUV2 */ 394572b676d7Smrg VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, 394672b676d7Smrg SISAllocSurface, 394772b676d7Smrg SISFreeSurface, 394872b676d7Smrg SISDisplaySurface, 394972b676d7Smrg SISStopSurface, 395072b676d7Smrg SISGetSurfaceAttribute, 395172b676d7Smrg SISSetSurfaceAttribute, 395272b676d7Smrg 0, 0, /* Rest will be filled in */ 395372b676d7Smrg 0, 395472b676d7Smrg NULL 395572b676d7Smrg }, 395672b676d7Smrg { 395772b676d7Smrg &SISImages[2], /* UYVY */ 395872b676d7Smrg VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, 395972b676d7Smrg SISAllocSurface, 396072b676d7Smrg SISFreeSurface, 396172b676d7Smrg SISDisplaySurface, 396272b676d7Smrg SISStopSurface, 396372b676d7Smrg SISGetSurfaceAttribute, 396472b676d7Smrg SISSetSurfaceAttribute, 396572b676d7Smrg 0, 0, /* Rest will be filled in */ 396672b676d7Smrg 0, 396772b676d7Smrg NULL 396872b676d7Smrg } 396972b676d7Smrg , 397072b676d7Smrg { 397172b676d7Smrg &SISImages[4], /* RV15 */ 397272b676d7Smrg VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, 397372b676d7Smrg SISAllocSurface, 397472b676d7Smrg SISFreeSurface, 397572b676d7Smrg SISDisplaySurface, 397672b676d7Smrg SISStopSurface, 397772b676d7Smrg SISGetSurfaceAttribute, 397872b676d7Smrg SISSetSurfaceAttribute, 397972b676d7Smrg 0, 0, /* Rest will be filled in */ 398072b676d7Smrg 0, 398172b676d7Smrg NULL 398272b676d7Smrg }, 398372b676d7Smrg { 398472b676d7Smrg &SISImages[5], /* RV16 */ 398572b676d7Smrg VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, 398672b676d7Smrg SISAllocSurface, 398772b676d7Smrg SISFreeSurface, 398872b676d7Smrg SISDisplaySurface, 398972b676d7Smrg SISStopSurface, 399072b676d7Smrg SISGetSurfaceAttribute, 399172b676d7Smrg SISSetSurfaceAttribute, 399272b676d7Smrg 0, 0, /* Rest will be filled in */ 399372b676d7Smrg 0, 399472b676d7Smrg NULL 399572b676d7Smrg }, 399672b676d7Smrg { 399772b676d7Smrg &SISImages[6], /* YVYU */ 399872b676d7Smrg VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, 399972b676d7Smrg SISAllocSurface, 400072b676d7Smrg SISFreeSurface, 400172b676d7Smrg SISDisplaySurface, 400272b676d7Smrg SISStopSurface, 400372b676d7Smrg SISGetSurfaceAttribute, 400472b676d7Smrg SISSetSurfaceAttribute, 400572b676d7Smrg 0, 0, /* Rest will be filled in */ 400672b676d7Smrg 0, 400772b676d7Smrg NULL 400872b676d7Smrg } 400972b676d7Smrg}; 401072b676d7Smrg 401172b676d7Smrgstatic void 401272b676d7SmrgSISInitOffscreenImages(ScreenPtr pScreen) 401372b676d7Smrg{ 401474c14cd6Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 401572b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 401672b676d7Smrg int i, num; 401772b676d7Smrg 401872b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA) num = NUMOFFSCRIMAGES_300; 401972b676d7Smrg else num = NUMOFFSCRIMAGES_315; 402072b676d7Smrg 402172b676d7Smrg for(i = 0; i < num; i++) { 402272b676d7Smrg SISOffscreenImages[i].max_width = DummyEncoding.width; 402372b676d7Smrg SISOffscreenImages[i].max_height = DummyEncoding.height; 402472b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA) { 402572b676d7Smrg SISOffscreenImages[i].attributes = &SISAttributes_300[0]; 402672b676d7Smrg SISOffscreenImages[i].num_attributes = SiSCountAttributes(&SISAttributes_300[0]); 402772b676d7Smrg } else { 402872b676d7Smrg SISOffscreenImages[i].attributes = &SISAttributes_315[0]; 402972b676d7Smrg SISOffscreenImages[i].num_attributes = SiSCountAttributes(&SISAttributes_315[0]); 403072b676d7Smrg if((pSiS->hasTwoOverlays) && (!(pSiS->SiS_SD2_Flags & SiS_SD2_SUPPORT760OO))) { 403172b676d7Smrg SISOffscreenImages[i].num_attributes--; 403272b676d7Smrg } 403372b676d7Smrg } 403472b676d7Smrg } 403572b676d7Smrg xf86XVRegisterOffscreenImages(pScreen, SISOffscreenImages, num); 403672b676d7Smrg} 403772b676d7Smrg 403872b676d7Smrg/*****************************************************************/ 403972b676d7Smrg/* BLIT ADAPTORS */ 404072b676d7Smrg/*****************************************************************/ 404172b676d7Smrg#ifdef INCL_YUV_BLIT_ADAPTOR 404272b676d7Smrg 404372b676d7Smrgstatic void 404472b676d7SmrgSISSetPortDefaultsBlit(ScrnInfoPtr pScrn, SISBPortPrivPtr pPriv) 404572b676d7Smrg{ 404672b676d7Smrg /* Default: Don't sync. */ 404772b676d7Smrg pPriv->vsync = 0; 404872b676d7Smrg} 404972b676d7Smrg 405072b676d7Smrgstatic void 405172b676d7SmrgSISResetVideoBlit(ScrnInfoPtr pScrn) 405272b676d7Smrg{ 405372b676d7Smrg} 405472b676d7Smrg 405572b676d7Smrgstatic XF86VideoAdaptorPtr 405672b676d7SmrgSISSetupBlitVideo(ScreenPtr pScreen) 405772b676d7Smrg{ 405874c14cd6Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 405972b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 406072b676d7Smrg XF86VideoAdaptorPtr adapt; 406172b676d7Smrg SISBPortPrivPtr pPriv; 406272b676d7Smrg int i; 406372b676d7Smrg 406472b676d7Smrg#ifdef SIS_USE_XAA 406572b676d7Smrg if(!pSiS->useEXA) { 406672b676d7Smrg if(!pSiS->AccelInfoPtr) return NULL; 406772b676d7Smrg } 406872b676d7Smrg#endif 406972b676d7Smrg 407074c14cd6Smrg if(!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + 407172b676d7Smrg (sizeof(DevUnion) * NUM_BLIT_PORTS) + 407272b676d7Smrg sizeof(SISBPortPrivRec)))) { 407372b676d7Smrg return NULL; 407472b676d7Smrg } 407572b676d7Smrg 407672b676d7Smrg adapt->type = XvWindowMask | XvInputMask | XvImageMask; 407772b676d7Smrg adapt->flags = 0; 407872b676d7Smrg adapt->name = "SIS 315/330 series Video Blitter"; 407972b676d7Smrg adapt->nEncodings = 1; 408072b676d7Smrg adapt->pEncodings = &DummyEncodingBlit; 408172b676d7Smrg adapt->nFormats = NUM_FORMATS; 408272b676d7Smrg adapt->pFormats = SISFormats; 408372b676d7Smrg adapt->nImages = NUM_IMAGES_BLIT; 408472b676d7Smrg adapt->pImages = SISImagesBlit; 408572b676d7Smrg adapt->pAttributes = SISAttributes_Blit; 408672b676d7Smrg adapt->nAttributes = NUM_ATTRIBUTES_BLIT; 408772b676d7Smrg adapt->nPorts = NUM_BLIT_PORTS; 408872b676d7Smrg adapt->pPortPrivates = (DevUnion*)(&adapt[1]); 408972b676d7Smrg 409072b676d7Smrg pSiS->blitPriv = (void *)(&adapt->pPortPrivates[NUM_BLIT_PORTS]); 409172b676d7Smrg pPriv = (SISBPortPrivPtr)(pSiS->blitPriv); 409272b676d7Smrg 409372b676d7Smrg for(i = 0; i < NUM_BLIT_PORTS; i++) { 409472b676d7Smrg adapt->pPortPrivates[i].uval = (ULong)(i); 409572b676d7Smrg#if defined(REGION_NULL) 409672b676d7Smrg REGION_NULL(pScreen, &pPriv->blitClip[i]); 409772b676d7Smrg#else 409872b676d7Smrg REGION_INIT(pScreen, &pPriv->blitClip[i], NullBox, 0); 409972b676d7Smrg#endif 410072b676d7Smrg pPriv->videoStatus[i] = 0; 410172b676d7Smrg pPriv->currentBuf[i] = 0; 410272b676d7Smrg pPriv->handle[i] = NULL; 410372b676d7Smrg } 410472b676d7Smrg 410572b676d7Smrg /* Scanline trigger not implemented by hardware! */ 410672b676d7Smrg pPriv->VBlankTriggerCRT1 = 0; /* SCANLINE_TRIGGER_ENABLE | SCANLINE_TR_CRT1; */ 410772b676d7Smrg pPriv->VBlankTriggerCRT2 = 0; /* SCANLINE_TRIGGER_ENABLE | SCANLINE_TR_CRT2; */ 410872b676d7Smrg if(pSiS->ChipType >= SIS_330) { 410972b676d7Smrg pPriv->AccelCmd = YUVRGB_BLIT_330; 411072b676d7Smrg } else { 411172b676d7Smrg pPriv->AccelCmd = YUVRGB_BLIT_325; 411272b676d7Smrg } 411372b676d7Smrg 411472b676d7Smrg adapt->PutVideo = NULL; 411572b676d7Smrg adapt->PutStill = NULL; 411672b676d7Smrg adapt->GetVideo = NULL; 411772b676d7Smrg adapt->GetStill = NULL; 411872b676d7Smrg adapt->StopVideo = (StopVideoFuncPtr)SISStopVideoBlit; 411972b676d7Smrg adapt->SetPortAttribute = (SetPortAttributeFuncPtr)SISSetPortAttributeBlit; 412072b676d7Smrg adapt->GetPortAttribute = (GetPortAttributeFuncPtr)SISGetPortAttributeBlit; 412172b676d7Smrg adapt->QueryBestSize = (QueryBestSizeFuncPtr)SISQueryBestSizeBlit; 412272b676d7Smrg adapt->PutImage = (PutImageFuncPtr)SISPutImageBlit; 412372b676d7Smrg adapt->QueryImageAttributes = SISQueryImageAttributesBlit; 412472b676d7Smrg 412572b676d7Smrg pSiS->blitadaptor = adapt; 412672b676d7Smrg 412772b676d7Smrg pSiS->xvVSync = MAKE_ATOM(sisxvvsync); 412872b676d7Smrg pSiS->xvSetDefaults = MAKE_ATOM(sisxvsetdefaults); 412972b676d7Smrg 413072b676d7Smrg SISResetVideoBlit(pScrn); 413172b676d7Smrg 413272b676d7Smrg /* Reset the properties to their defaults */ 413372b676d7Smrg SISSetPortDefaultsBlit(pScrn, pPriv); 413472b676d7Smrg 413572b676d7Smrg return adapt; 413672b676d7Smrg} 413772b676d7Smrg 413872b676d7Smrgstatic int 413972b676d7SmrgSISGetPortAttributeBlit(ScrnInfoPtr pScrn, Atom attribute, 414072b676d7Smrg INT32 *value, ULong index) 414172b676d7Smrg{ 414272b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 414372b676d7Smrg SISBPortPrivPtr pPriv = (SISBPortPrivPtr)(pSiS->blitPriv); 414472b676d7Smrg 414572b676d7Smrg if(attribute == pSiS->xvVSync) { 414672b676d7Smrg *value = pPriv->vsync; 414772b676d7Smrg } else return BadMatch; 414872b676d7Smrg return Success; 414972b676d7Smrg} 415072b676d7Smrg 415172b676d7Smrgstatic int 415272b676d7SmrgSISSetPortAttributeBlit(ScrnInfoPtr pScrn, Atom attribute, 415372b676d7Smrg INT32 value, ULong index) 415472b676d7Smrg{ 415572b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 415672b676d7Smrg SISBPortPrivPtr pPriv = (SISBPortPrivPtr)(pSiS->blitPriv); 415772b676d7Smrg 415872b676d7Smrg if(attribute == pSiS->xvVSync) { 415972b676d7Smrg if((value < 0) || (value > 1)) return BadValue; 416072b676d7Smrg pPriv->vsync = value; 416172b676d7Smrg } else if(attribute == pSiS->xvSetDefaults) { 416272b676d7Smrg SISSetPortDefaultsBlit(pScrn, pPriv); 416372b676d7Smrg } else return BadMatch; 416472b676d7Smrg return Success; 416572b676d7Smrg} 416672b676d7Smrg 416772b676d7Smrgstatic void 416872b676d7SmrgSISStopVideoBlit(ScrnInfoPtr pScrn, ULong index, Bool shutdown) 416972b676d7Smrg{ 417072b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 417172b676d7Smrg SISBPortPrivPtr pPriv = (SISBPortPrivPtr)(pSiS->blitPriv); 417272b676d7Smrg 417372b676d7Smrg /* This shouldn't be called for blitter adaptors due to 417472b676d7Smrg * adapt->flags but we provide it anyway. 417572b676d7Smrg */ 417672b676d7Smrg 4177e47418d9Smrg if(index >= NUM_BLIT_PORTS) return; 417872b676d7Smrg 417972b676d7Smrg REGION_EMPTY(pScrn->pScreen, &pPriv->blitClip[index]); 418072b676d7Smrg 418172b676d7Smrg if(shutdown) { 418272b676d7Smrg (*pSiS->SyncAccel)(pScrn); 418372b676d7Smrg pPriv->videoStatus[index] = 0; 418472b676d7Smrg SISFreeFBMemory(pScrn, &pPriv->handle[(int)index]); 418572b676d7Smrg } 418672b676d7Smrg} 418772b676d7Smrg 418872b676d7Smrgstatic int 418972b676d7SmrgSISPutImageBlit( 419072b676d7Smrg ScrnInfoPtr pScrn, 419172b676d7Smrg short src_x, short src_y, 419272b676d7Smrg short drw_x, short drw_y, 419372b676d7Smrg short src_w, short src_h, 419472b676d7Smrg short drw_w, short drw_h, 419572b676d7Smrg int id, UChar *buf, 419672b676d7Smrg short width, short height, 419772b676d7Smrg Bool sync, 419872b676d7Smrg RegionPtr clipBoxes, ULong index, 419972b676d7Smrg DrawablePtr pDraw 420072b676d7Smrg){ 420172b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 420272b676d7Smrg SISBPortPrivPtr pPriv = (SISBPortPrivPtr)(pSiS->blitPriv); 420372b676d7Smrg#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,1,99,1,0) 420472b676d7Smrg XAAInfoRecPtr pXAA = pSiS->AccelInfoPtr; 420572b676d7Smrg#endif 420672b676d7Smrg BoxPtr pbox = REGION_RECTS(clipBoxes); 420772b676d7Smrg int nbox = REGION_NUM_RECTS(clipBoxes); 420872b676d7Smrg CARD32 dstbase = 0, offsety, offsetuv, temp; 420972b676d7Smrg int totalSize, bytesize=0, h, w, wb, srcPitch; 421072b676d7Smrg int xoffset = 0, yoffset = 0, left, right, top, bottom; 421172b676d7Smrg UChar *ybases, *ubases = NULL, *vbases = NULL, *myubases, *myvbases; 421272b676d7Smrg UChar *ybased, *uvbased, packed; 421372b676d7Smrg CARD16 *myuvbased; 421472b676d7Smrg SiS_Packet12_YUV MyPacket; 421574fcc364Smrg#if 0 421674fcc364Smrg#ifdef SISMERGED 421772b676d7Smrg Bool first; 421874fcc364Smrg#endif 421974fcc364Smrg#endif 422072b676d7Smrg 4221e47418d9Smrg if(index >= NUM_BLIT_PORTS) return BadMatch; 422272b676d7Smrg 422372b676d7Smrg if(!height || !width) return Success; 422472b676d7Smrg 422572b676d7Smrg switch(id) { 422672b676d7Smrg case PIXEL_FMT_YV12: 422772b676d7Smrg case PIXEL_FMT_I420: 422872b676d7Smrg case PIXEL_FMT_NV12: 422972b676d7Smrg case PIXEL_FMT_NV21: 423072b676d7Smrg srcPitch = (width + 7) & ~7; /* Should come this way anyway */ 423172b676d7Smrg bytesize = srcPitch * height; 423272b676d7Smrg totalSize = (bytesize * 3) >> 1; 423372b676d7Smrg break; 423472b676d7Smrg case PIXEL_FMT_YUY2: 423572b676d7Smrg case PIXEL_FMT_UYVY: 423672b676d7Smrg case PIXEL_FMT_YVYU: 423772b676d7Smrg srcPitch = ((width << 1) + 3) & ~3; 423872b676d7Smrg /* Size = width * 2 * height */ 423972b676d7Smrg totalSize = srcPitch * height; 424072b676d7Smrg bytesize = 0; 424172b676d7Smrg break; 424272b676d7Smrg default: 424372b676d7Smrg return BadMatch; 424472b676d7Smrg } 424572b676d7Smrg 424672b676d7Smrg /* allocate memory (we do doublebuffering) */ 424772b676d7Smrg if(!(pPriv->bufAddr[index][0] = SISAllocateFBMemory(pScrn, &pPriv->handle[index], totalSize << 1))) 424872b676d7Smrg return BadAlloc; 424972b676d7Smrg 425072b676d7Smrg pPriv->bufAddr[index][1] = pPriv->bufAddr[index][0] + totalSize; 425172b676d7Smrg 425272b676d7Smrg if(drw_w > width) { 425372b676d7Smrg xoffset = (drw_w - width) >> 1; 425472b676d7Smrg } 425572b676d7Smrg if(drw_h > (height & ~1)) { 425672b676d7Smrg yoffset = (drw_h - height) >> 1; 425772b676d7Smrg } 425872b676d7Smrg 425972b676d7Smrg if(xoffset || yoffset) { 426072b676d7Smrg#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,3,99,3,0) 426172b676d7Smrg if(!RegionsEqual(&pPriv->blitClip[index], clipBoxes)) { 426272b676d7Smrg#else 426372b676d7Smrg if(!REGION_EQUAL(pScrn->pScreen, &pPriv->blitClip[index], clipBoxes)) { 426472b676d7Smrg#endif 426572b676d7Smrg#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,1,99,1,0) 426672b676d7Smrg (*pXAA->FillSolidRects)(pScrn, 0x00000000, GXcopy, ~0, 426772b676d7Smrg REGION_NUM_RECTS(clipBoxes), 426872b676d7Smrg REGION_RECTS(clipBoxes)); 426972b676d7Smrg#else 427072b676d7Smrg xf86XVFillKeyHelper(pScrn->pScreen, 0x00000000, clipBoxes); 427172b676d7Smrg#endif 427272b676d7Smrg REGION_COPY(pScrn->pScreen, &pPriv->blitClip[index], clipBoxes); 427372b676d7Smrg } 427472b676d7Smrg } 427572b676d7Smrg 427672b676d7Smrg memset(&MyPacket, 0, sizeof(MyPacket)); 427772b676d7Smrg 427872b676d7Smrg ybased = pSiS->FbBase + pPriv->bufAddr[index][pPriv->currentBuf[index]]; 427972b676d7Smrg uvbased = pSiS->FbBase + pPriv->bufAddr[index][pPriv->currentBuf[index]] + bytesize; 428072b676d7Smrg 428172b676d7Smrg ybases = buf; 428272b676d7Smrg packed = 0; 428372b676d7Smrg 428472b676d7Smrg switch(id) { 428572b676d7Smrg case PIXEL_FMT_YV12: 428672b676d7Smrg vbases = buf + bytesize; 428772b676d7Smrg ubases = buf + bytesize*5/4; 428872b676d7Smrg break; 428972b676d7Smrg case PIXEL_FMT_I420: 429072b676d7Smrg ubases = buf + bytesize; 429172b676d7Smrg vbases = buf + bytesize*5/4; 429272b676d7Smrg break; 429372b676d7Smrg case PIXEL_FMT_NV12: 429472b676d7Smrg MyPacket.P12_Command = YUV_FORMAT_NV12; 429572b676d7Smrg break; 429672b676d7Smrg case PIXEL_FMT_NV21: 429772b676d7Smrg MyPacket.P12_Command = YUV_FORMAT_NV21; 429872b676d7Smrg break; 429972b676d7Smrg case PIXEL_FMT_YUY2: 430072b676d7Smrg MyPacket.P12_Command = YUV_FORMAT_YUY2; 430172b676d7Smrg packed = 1; 430272b676d7Smrg break; 430372b676d7Smrg case PIXEL_FMT_UYVY: 430472b676d7Smrg MyPacket.P12_Command = YUV_FORMAT_UYVY; 430572b676d7Smrg packed = 1; 430672b676d7Smrg break; 430772b676d7Smrg case PIXEL_FMT_YVYU: 430872b676d7Smrg MyPacket.P12_Command = YUV_FORMAT_YVYU; 430972b676d7Smrg packed = 1; 431072b676d7Smrg break; 431172b676d7Smrg default: 431272b676d7Smrg return BadMatch; 431372b676d7Smrg } 431472b676d7Smrg 431572b676d7Smrg switch(id) { 431672b676d7Smrg case PIXEL_FMT_YV12: 431772b676d7Smrg case PIXEL_FMT_I420: 431872b676d7Smrg MyPacket.P12_Command = YUV_FORMAT_NV12; 431972b676d7Smrg /* Copy y plane */ 432072b676d7Smrg SiSMemCopyToVideoRam(pSiS, ybased, ybases, bytesize); 432172b676d7Smrg /* Copy u/v planes */ 432272b676d7Smrg wb = srcPitch >> 1; 432372b676d7Smrg h = height >> 1; 432472b676d7Smrg while(h--) { 432572b676d7Smrg myuvbased = (CARD16*)uvbased; 432672b676d7Smrg myubases = ubases; 432772b676d7Smrg myvbases = vbases; 432872b676d7Smrg w = wb; 432972b676d7Smrg while(w--) { 433072b676d7Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN 433172b676d7Smrg temp = (*myubases++) << 8; 433272b676d7Smrg temp |= (*myvbases++); 433372b676d7Smrg#else 433472b676d7Smrg temp = (*myvbases++) << 8; 433572b676d7Smrg temp |= (*myubases++); 433672b676d7Smrg#endif 433772b676d7Smrg *myuvbased++ = temp; 433872b676d7Smrg } 433972b676d7Smrg uvbased += srcPitch; 434072b676d7Smrg ubases += wb; 434172b676d7Smrg vbases += wb; 434272b676d7Smrg } 434372b676d7Smrg break; 434472b676d7Smrg default: 434572b676d7Smrg SiSMemCopyToVideoRam(pSiS, ybased, ybases, totalSize); 434672b676d7Smrg } 434772b676d7Smrg 434872b676d7Smrg dstbase += FBOFFSET; 434972b676d7Smrg 435072b676d7Smrg MyPacket.P12_Header0 = SIS_PACKET12_HEADER0; 435172b676d7Smrg MyPacket.P12_Header1 = SIS_PACKET12_HEADER1; 435272b676d7Smrg MyPacket.P12_Null1 = SIS_NIL_CMD; 435372b676d7Smrg MyPacket.P12_Null2 = SIS_NIL_CMD; 435472b676d7Smrg MyPacket.P12_YPitch = MyPacket.P12_UVPitch = srcPitch; 435572b676d7Smrg MyPacket.P12_DstAddr = dstbase; 435672b676d7Smrg MyPacket.P12_DstPitch = pSiS->scrnOffset; 435772b676d7Smrg MyPacket.P12_DstHeight = 0x0fff; 435872b676d7Smrg 435972b676d7Smrg MyPacket.P12_Command |= pPriv->AccelCmd | 436072b676d7Smrg SRCVIDEO | 436172b676d7Smrg PATFG | 436272b676d7Smrg pSiS->SiS310_AccelDepth | 436372b676d7Smrg YUV_CMD_YUV | 436472b676d7Smrg DSTVIDEO; 436572b676d7Smrg 436672b676d7Smrg 436772b676d7Smrg#if 0 /* Not implemented by hardware! */ 436872b676d7Smrg if(pPriv->vsync) { 436972b676d7Smrg#ifdef SISMERGED 437072b676d7Smrg if(!pSiS->MergedFB) { 437172b676d7Smrg#endif 437272b676d7Smrg#ifdef SISDUALHEAD 437372b676d7Smrg if(pSiS->DualHeadMode) { 437472b676d7Smrg if(pSiS->SecondHead) { 437572b676d7Smrg MyPacket.P12_Command |= pPriv->VBlankTriggerCRT1; 437672b676d7Smrg } else { 437772b676d7Smrg MyPacket.P12_Command |= pPriv->VBlankTriggerCRT2; 437872b676d7Smrg } 437972b676d7Smrg } else { 438072b676d7Smrg#endif 438172b676d7Smrg Bool IsSlaveMode = SiSBridgeIsInSlaveMode(pScrn); 438272b676d7Smrg if((pSiS->VBFlags & DISPTYPE_DISP2) && !IsSlaveMode) 438372b676d7Smrg MyPacket.P12_Command |= pPriv->VBlankTriggerCRT2; 438472b676d7Smrg else if((pSiS->VBFlags & DISPTYPE_DISP1) || IsSlaveMode) 438572b676d7Smrg MyPacket.P12_Command |= pPriv->VBlankTriggerCRT1; 438672b676d7Smrg#ifdef SISDUALHEAD 438772b676d7Smrg } 438872b676d7Smrg#endif 438972b676d7Smrg#ifdef SISMERGED 439072b676d7Smrg } 439172b676d7Smrg#endif 439272b676d7Smrg } 439372b676d7Smrg#endif 439472b676d7Smrg 439574fcc364Smrg#if 0 439674fcc364Smrg#ifdef SISMERGED 439772b676d7Smrg first = TRUE; 439874fcc364Smrg#endif 439974fcc364Smrg#endif 440072b676d7Smrg while(nbox--) { 440172b676d7Smrg left = pbox->x1; 440272b676d7Smrg if(left >= drw_x + xoffset + width) goto mycont; 440372b676d7Smrg 440472b676d7Smrg right = pbox->x2; 440572b676d7Smrg if(right <= drw_x + xoffset) goto mycont; 440672b676d7Smrg 440772b676d7Smrg top = pbox->y1; 440872b676d7Smrg if(top >= drw_y + yoffset + height) goto mycont; 440972b676d7Smrg 441072b676d7Smrg bottom = pbox->y2; 441172b676d7Smrg if(bottom <= drw_y + yoffset) goto mycont; 441272b676d7Smrg 441372b676d7Smrg if(left < (drw_x + xoffset)) left = drw_x + xoffset; 441472b676d7Smrg if(right > (drw_x + xoffset + width)) right = drw_x + xoffset + width; 441572b676d7Smrg if(top < (drw_y + yoffset)) top = drw_y + yoffset; 441672b676d7Smrg if(bottom > (drw_y + yoffset + height)) bottom = drw_y + yoffset + height; 441772b676d7Smrg 441872b676d7Smrg MyPacket.P12_DstX = left; 441972b676d7Smrg MyPacket.P12_DstY = top; 442072b676d7Smrg MyPacket.P12_RectWidth = right - left; 442172b676d7Smrg MyPacket.P12_RectHeight = bottom - top; 442272b676d7Smrg 442372b676d7Smrg#if 0 442472b676d7Smrg#ifdef SISMERGED 442572b676d7Smrg if((first) && (pSiS->MergedFB)) { 442672b676d7Smrg int scrwidth = ((SiSMergedDisplayModePtr)pSiS->CurrentLayout.mode->Private)->CRT2->HDisplay; 442772b676d7Smrg int scrheight = ((SiSMergedDisplayModePtr)pSiS->CurrentLayout.mode->Private)->CRT2->VDisplay; 442872b676d7Smrg if( (right < pSiS->CRT2pScrn->frameX0) || 442972b676d7Smrg (left >= pSiS->CRT2pScrn->frameX0 + scrwidth) || 443072b676d7Smrg (bottom < pSiS->CRT2pScrn->frameY0) || 443172b676d7Smrg (top >= pSiS->CRT2pScrn->frameY0 + scrheight) ) { 443272b676d7Smrg MyPacket.P12_Command |= pPriv->VBlankTriggerCRT1; 443372b676d7Smrg } else { 443472b676d7Smrg MyPacket.P12_Command |= pPriv->VBlankTriggerCRT2; 443572b676d7Smrg } 443672b676d7Smrg } 443772b676d7Smrg#endif 443872b676d7Smrg#endif 443972b676d7Smrg 444072b676d7Smrg offsety = offsetuv = 0; 444172b676d7Smrg if(packed) { 444272b676d7Smrg if(pbox->y1 > drw_y + yoffset) { 444372b676d7Smrg offsetuv = (pbox->y1 - drw_y - yoffset) * srcPitch; 444472b676d7Smrg } 444572b676d7Smrg if(pbox->x1 > drw_x + xoffset) { 444672b676d7Smrg offsetuv += ((pbox->x1 - drw_x - xoffset) << 1); 444772b676d7Smrg if(offsetuv & 3) { 444872b676d7Smrg#if 0 /* Paint over covering object - no */ 444972b676d7Smrg if(MyPacket.P12_DstX > 0) { 445072b676d7Smrg offsetuv &= ~3; 445172b676d7Smrg MyPacket.P12_DstX--; 445272b676d7Smrg MyPacket.P12_RectWidth++; 445372b676d7Smrg } else { 445472b676d7Smrg#endif 445572b676d7Smrg offsetuv = (offsetuv + 3) & ~3; 445672b676d7Smrg MyPacket.P12_DstX++; 445772b676d7Smrg MyPacket.P12_RectWidth--; 445872b676d7Smrg#if 0 445972b676d7Smrg } 446072b676d7Smrg#endif 446172b676d7Smrg } 446272b676d7Smrg } 446372b676d7Smrg } else { 446472b676d7Smrg if(pbox->y1 > drw_y + yoffset) { 446572b676d7Smrg offsety = (pbox->y1 - drw_y - yoffset) * srcPitch; 446672b676d7Smrg offsetuv = ((pbox->y1 - drw_y - yoffset) >> 1) * srcPitch; 446772b676d7Smrg } 446872b676d7Smrg if(pbox->x1 > drw_x + xoffset) { 446972b676d7Smrg offsety += (pbox->x1 - drw_x - xoffset); 447072b676d7Smrg offsetuv += (pbox->x1 - drw_x - xoffset); 447172b676d7Smrg if(offsetuv & 1) { 447272b676d7Smrg offsety++; 447372b676d7Smrg offsetuv++; 447472b676d7Smrg MyPacket.P12_DstX++; 447572b676d7Smrg MyPacket.P12_RectWidth--; 447672b676d7Smrg } 447772b676d7Smrg } 447872b676d7Smrg } 447972b676d7Smrg 448072b676d7Smrg if(!MyPacket.P12_RectWidth) continue; 448172b676d7Smrg 448272b676d7Smrg MyPacket.P12_YSrcAddr = pPriv->bufAddr[index][pPriv->currentBuf[index]] + offsety + FBOFFSET; 448372b676d7Smrg MyPacket.P12_UVSrcAddr = pPriv->bufAddr[index][pPriv->currentBuf[index]] + bytesize + offsetuv + FBOFFSET; 448472b676d7Smrg SISWriteBlitPacket(pSiS, (CARD32*)&MyPacket); 448572b676d7Smrg#if 0 448672b676d7Smrg MyPacket.P12_Command &= ~(pPriv->VBlankTriggerCRT1 | pPriv->VBlankTriggerCRT2); 448772b676d7Smrg#endif 448874fcc364Smrg#if 0 448974fcc364Smrg#ifdef SISMERGED 449072b676d7Smrg first = FALSE; 449174fcc364Smrg#endif 449274fcc364Smrg#endif 449372b676d7Smrgmycont: 449472b676d7Smrg pbox++; 449572b676d7Smrg } 449672b676d7Smrg 449772b676d7Smrg#if 0 449872b676d7Smrg { 449972b676d7Smrg int debug = 0; 450072b676d7Smrg while( (SIS_MMIO_IN16(pSiS->IOBase, Q_STATUS+2) & 0x8000) != 0x8000) { debug++; }; 450172b676d7Smrg while( (SIS_MMIO_IN16(pSiS->IOBase, Q_STATUS+2) & 0x8000) != 0x8000) { debug++; }; 450272b676d7Smrg xf86DrvMsg(0, X_INFO, "vsync %d, debug %d\n", pPriv->vsync, debug); 450372b676d7Smrg } 450472b676d7Smrg#endif 450572b676d7Smrg 450672b676d7Smrg pPriv->currentBuf[index] ^= 1; 450772b676d7Smrg 450872b676d7Smrg UpdateCurrentTime(); 450972b676d7Smrg pPriv->freeTime[index] = currentTime.milliseconds + FREE_DELAY; 451072b676d7Smrg pPriv->videoStatus[index] = FREE_TIMER; 451172b676d7Smrg 451272b676d7Smrg pSiS->VideoTimerCallback = SISVideoTimerCallback; 451372b676d7Smrg 451472b676d7Smrg return Success; 451572b676d7Smrg} 451672b676d7Smrg 451772b676d7Smrgstatic int 451872b676d7SmrgSISQueryImageAttributesBlit( 451972b676d7Smrg ScrnInfoPtr pScrn, 452072b676d7Smrg int id, 452172b676d7Smrg UShort *w, UShort *h, 452272b676d7Smrg int *pitches, int *offsets 452372b676d7Smrg){ 452472b676d7Smrg int pitchY, pitchUV; 452572b676d7Smrg int size, sizeY, sizeUV; 452672b676d7Smrg 452772b676d7Smrg if(*w > DummyEncodingBlit.width) *w = DummyEncodingBlit.width; 452872b676d7Smrg if(*h > DummyEncodingBlit.height) *h = DummyEncodingBlit.height; 452972b676d7Smrg 453072b676d7Smrg switch(id) { 453172b676d7Smrg case PIXEL_FMT_YV12: 453272b676d7Smrg case PIXEL_FMT_I420: 453372b676d7Smrg *w = (*w + 7) & ~7; 453472b676d7Smrg *h = (*h + 1) & ~1; 453572b676d7Smrg pitchY = *w; 453672b676d7Smrg pitchUV = *w >> 1; 453772b676d7Smrg if(pitches) { 453872b676d7Smrg pitches[0] = pitchY; 453972b676d7Smrg pitches[1] = pitches[2] = pitchUV; 454072b676d7Smrg } 454172b676d7Smrg sizeY = pitchY * (*h); 454272b676d7Smrg sizeUV = pitchUV * ((*h) >> 1); 454372b676d7Smrg if(offsets) { 454472b676d7Smrg offsets[0] = 0; 454572b676d7Smrg offsets[1] = sizeY; 454672b676d7Smrg offsets[2] = sizeY + sizeUV; 454772b676d7Smrg } 454872b676d7Smrg size = sizeY + (sizeUV << 1); 454972b676d7Smrg break; 455072b676d7Smrg case PIXEL_FMT_NV12: 455172b676d7Smrg case PIXEL_FMT_NV21: 455272b676d7Smrg *w = (*w + 7) & ~7; 455372b676d7Smrg pitchY = *w; 455472b676d7Smrg pitchUV = *w; 455572b676d7Smrg if(pitches) { 455672b676d7Smrg pitches[0] = pitchY; 455772b676d7Smrg pitches[1] = pitchUV; 455872b676d7Smrg } 455972b676d7Smrg sizeY = pitchY * (*h); 456072b676d7Smrg sizeUV = pitchUV * ((*h) >> 1); 456172b676d7Smrg if(offsets) { 456272b676d7Smrg offsets[0] = 0; 456372b676d7Smrg offsets[1] = sizeY; 456472b676d7Smrg } 456572b676d7Smrg size = sizeY + (sizeUV << 1); 456672b676d7Smrg break; 456772b676d7Smrg case PIXEL_FMT_YUY2: 456872b676d7Smrg case PIXEL_FMT_UYVY: 456972b676d7Smrg case PIXEL_FMT_YVYU: 457072b676d7Smrg default: 457172b676d7Smrg *w = (*w + 1) & ~1; 457272b676d7Smrg pitchY = *w << 1; 457372b676d7Smrg if(pitches) pitches[0] = pitchY; 457472b676d7Smrg if(offsets) offsets[0] = 0; 457572b676d7Smrg size = pitchY * (*h); 457672b676d7Smrg break; 457772b676d7Smrg } 457872b676d7Smrg 457972b676d7Smrg return size; 458072b676d7Smrg} 458172b676d7Smrg 458272b676d7Smrgstatic void 458372b676d7SmrgSISQueryBestSizeBlit( 458472b676d7Smrg ScrnInfoPtr pScrn, 458572b676d7Smrg Bool motion, 458672b676d7Smrg short vid_w, short vid_h, 458772b676d7Smrg short drw_w, short drw_h, 458872b676d7Smrg unsigned int *p_w, unsigned int *p_h, 458972b676d7Smrg ULong index 459072b676d7Smrg){ 459172b676d7Smrg /* We cannot scale */ 459272b676d7Smrg *p_w = vid_w; 459372b676d7Smrg *p_h = vid_h; 459472b676d7Smrg} 459572b676d7Smrg#endif /* INCL_YUV */ 459672b676d7Smrg 459772b676d7Smrg/*****************************************/ 459872b676d7Smrg/* TIMER CALLBACK */ 459972b676d7Smrg/*****************************************/ 460072b676d7Smrg 460172b676d7Smrgstatic void 460272b676d7SmrgSISVideoTimerCallback(ScrnInfoPtr pScrn, Time now) 460372b676d7Smrg{ 460472b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 460572b676d7Smrg SISPortPrivPtr pPriv = NULL; 460672b676d7Smrg#ifdef INCL_YUV_BLIT_ADAPTOR 460772b676d7Smrg SISBPortPrivPtr pPrivBlit = NULL; 460872b676d7Smrg#endif 460972b676d7Smrg UChar sridx, cridx; 461072b676d7Smrg Bool setcallback = FALSE; 461172b676d7Smrg 461272b676d7Smrg if(!pScrn->vtSema) return; 461372b676d7Smrg 461472b676d7Smrg if(pSiS->adaptor) { 461572b676d7Smrg pPriv = GET_PORT_PRIVATE(pScrn); 461672b676d7Smrg if(!pPriv->videoStatus) pPriv = NULL; 461772b676d7Smrg } 461872b676d7Smrg 461972b676d7Smrg if(pPriv) { 462072b676d7Smrg if(pPriv->videoStatus & TIMER_MASK) { 462172b676d7Smrg if(pPriv->videoStatus & OFF_TIMER) { 462272b676d7Smrg setcallback = TRUE; 462372b676d7Smrg if(pPriv->offTime < now) { 462472b676d7Smrg /* Turn off the overlay */ 462572b676d7Smrg sridx = inSISREG(SISSR); cridx = inSISREG(SISCR); 462672b676d7Smrg close_overlay(pSiS, pPriv); 462772b676d7Smrg outSISREG(SISSR, sridx); outSISREG(SISCR, cridx); 462872b676d7Smrg pPriv->mustwait = 1; 462972b676d7Smrg pPriv->videoStatus = FREE_TIMER; 463072b676d7Smrg pPriv->freeTime = now + FREE_DELAY; 463172b676d7Smrg } 463272b676d7Smrg } else if(pPriv->videoStatus & FREE_TIMER) { 463372b676d7Smrg if(pPriv->freeTime < now) { 463472b676d7Smrg SISFreeFBMemory(pScrn, &pPriv->handle); 463572b676d7Smrg pPriv->mustwait = 1; 463672b676d7Smrg pPriv->videoStatus = 0; 463772b676d7Smrg } else { 463872b676d7Smrg setcallback = TRUE; 463972b676d7Smrg } 464072b676d7Smrg } 464172b676d7Smrg } 464272b676d7Smrg } 464372b676d7Smrg 464472b676d7Smrg#ifdef INCL_YUV_BLIT_ADAPTOR 464572b676d7Smrg if(pSiS->blitadaptor) { 464672b676d7Smrg int i; 464772b676d7Smrg pPrivBlit = (SISBPortPrivPtr)(pSiS->blitPriv); 464872b676d7Smrg for(i = 0; i < NUM_BLIT_PORTS; i++) { 464972b676d7Smrg if(pPrivBlit->videoStatus[i] & FREE_TIMER) { 465072b676d7Smrg if(pPrivBlit->freeTime[i] < now) { 465172b676d7Smrg SISFreeFBMemory(pScrn, &pPrivBlit->handle[i]); 465272b676d7Smrg pPrivBlit->videoStatus[i] = 0; 465372b676d7Smrg } else { 465472b676d7Smrg setcallback = TRUE; 465572b676d7Smrg } 465672b676d7Smrg } 465772b676d7Smrg } 465872b676d7Smrg } 465972b676d7Smrg#endif 466072b676d7Smrg 466172b676d7Smrg pSiS->VideoTimerCallback = (setcallback) ? SISVideoTimerCallback : NULL; 466272b676d7Smrg} 466372b676d7Smrg 4664