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