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