73d1e76463
Tested by todd. ok Matthieu.
4652 lines
138 KiB
C
4652 lines
138 KiB
C
/*
|
|
* Xv driver for SiS 300, 315 and 330 series.
|
|
*
|
|
* Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1) Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2) Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3) The name of the author may not be used to endorse or promote products
|
|
* derived from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
* Author: Thomas Winischhofer <thomas@winischhofer.net>
|
|
*
|
|
* Formerly based on a mostly non-working code fragment for the 630 by
|
|
* Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan which is
|
|
* Copyright (C) 2000 Silicon Integrated Systems Corp, Inc.
|
|
*
|
|
* Basic structure based on the mga Xv driver by Mark Vojkovich
|
|
* and i810 Xv driver by Jonathan Bian <jonathan.bian@intel.com>.
|
|
*
|
|
* All comments in this file are by Thomas Winischhofer.
|
|
*
|
|
* The overlay adaptor supports the following chipsets:
|
|
* SiS300: No registers >0x65, two overlays (one used for CRT1, one for CRT2)
|
|
* SiS630/730: No registers >0x6b, two overlays (one used for CRT1, one for CRT2)
|
|
* SiS550: Full register range, two overlays (one used for CRT1, one for CRT2)
|
|
* SiS315: Full register range, one overlay (used for both CRT1 and CRT2 alt.)
|
|
* SiS650/740: Full register range, one overlay (used for both CRT1 and CRT2 alt.)
|
|
* SiSM650/651: Full register range, two overlays (one used for CRT1, one for CRT2)
|
|
* SiS330: Full register range, one overlay (used for both CRT1 and CRT2 alt.)
|
|
* SiS661/741/760: Full register range, two overlays (one used for CRT1, one for CRT2)
|
|
* SiS340: - ? overlays. Extended registers for DDA.
|
|
* SiS761: - ? overlays. Extended registers for DDA.
|
|
* XGI Volari V3XT/V5/V8: 1 Overlay. Extended registers for DDA.
|
|
*
|
|
* Help for reading the code:
|
|
* 315/550/650/740/M650/651/330/661/741/76x/340/XGI = SIS_315_VGA
|
|
* 300/630/730 = SIS_300_VGA
|
|
* For chipsets with 2 overlays, hasTwoOverlays will be true
|
|
*
|
|
* Notes on display modes:
|
|
*
|
|
* -) dual head mode:
|
|
* DISPMODE is either SINGLE1 or SINGLE2, hence you need to check dualHeadMode flag
|
|
* DISPMODE is _never_ MIRROR.
|
|
* a) Chipsets with 2 overlays:
|
|
* 315/330 series: Only half sized overlays available (width 960), 660: 1536
|
|
* Overlay 1 is used on CRT1, overlay 2 for CRT2.
|
|
* b) Chipsets with 1 overlay:
|
|
* Full size overlays available.
|
|
* Overlay is used for either CRT1 or CRT2
|
|
* -) merged fb mode:
|
|
* a) Chipsets with 2 overlays:
|
|
* 315/330 series: Only half sized overlays available (width 960), 660: 1536
|
|
* DISPMODE is always MIRROR. Overlay 1 is used for CRT1, overlay 2 for CRT2.
|
|
* b) Chipsets with 1 overlay:
|
|
* Full size overlays available.
|
|
* DISPMODE is either SINGLE1 or SINGLE2. Overlay is used accordingly on either
|
|
* CRT1 or CRT2 (automatically, where it is located)
|
|
* -) mirror mode (without dualhead or mergedfb)
|
|
* a) Chipsets with 2 overlays:
|
|
* 315/330 series: Only half sized overlays available (width 960), 660: 1536
|
|
* DISPMODE is MIRROR. Overlay 1 is used for CRT1, overlay 2 for CRT2.
|
|
* b) Chipsets with 1 overlay:
|
|
* Full size overlays available.
|
|
* DISPMODE is either SINGLE1 or SINGLE2. Overlay is used depending on
|
|
* XvOnCRT2 flag.
|
|
*
|
|
* About the video blitter:
|
|
* The video blitter adaptor supports 16 ports. By default, adaptor 0 will
|
|
* be the overlay adaptor, adaptor 1 the video blitter. The option XvDefaultAdaptor
|
|
* allows reversing this.
|
|
* Since SiS does not provide information on the 3D engine, I could not
|
|
* implement scaling. Instead, the driver paints a black border around the unscaled
|
|
* video if the destination area is bigger than the video.
|
|
*
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include "sis.h"
|
|
#ifdef SIS_USE_XAA
|
|
#include "xf86fbman.h"
|
|
#endif
|
|
#include "regionstr.h"
|
|
|
|
#include "xf86xv.h"
|
|
#include <X11/extensions/Xv.h>
|
|
#include "dixstruct.h"
|
|
#include "fourcc.h"
|
|
|
|
#define SIS_NEED_inSISREG
|
|
#define SIS_NEED_outSISREG
|
|
#define SIS_NEED_inSISIDXREG
|
|
#define SIS_NEED_outSISIDXREG
|
|
#define SIS_NEED_setSISIDXREGmask
|
|
#define SIS_NEED_MYMMIO
|
|
#include "sis_regs.h"
|
|
|
|
#ifdef INCL_YUV_BLIT_ADAPTOR
|
|
#include "sis310_accel.h"
|
|
#endif
|
|
|
|
#include "sis_video.h"
|
|
|
|
/*********************************
|
|
* Raw register access *
|
|
*********************************/
|
|
|
|
#if 0
|
|
static CARD32 _sisread(SISPtr pSiS, CARD32 reg)
|
|
{
|
|
return *(pSiS->IOBase + reg);
|
|
}
|
|
|
|
static void _siswrite(SISPtr pSiS, CARD32 reg, CARD32 data)
|
|
{
|
|
*(pSiS->IOBase + reg) = data;
|
|
}
|
|
#endif
|
|
|
|
static CARD8 getsrreg(SISPtr pSiS, CARD8 reg)
|
|
{
|
|
CARD8 ret;
|
|
inSISIDXREG(SISSR, reg, ret);
|
|
return ret;
|
|
}
|
|
|
|
static CARD8 getvideoreg(SISPtr pSiS, CARD8 reg)
|
|
{
|
|
CARD8 ret;
|
|
inSISIDXREG(SISVID, reg, ret);
|
|
return ret;
|
|
}
|
|
|
|
static __inline void setvideoreg(SISPtr pSiS, CARD8 reg, CARD8 data)
|
|
{
|
|
outSISIDXREG(SISVID, reg, data);
|
|
}
|
|
|
|
static __inline void setvideoregmask(SISPtr pSiS, CARD8 reg, CARD8 data, CARD8 mask)
|
|
{
|
|
setSISIDXREGmask(SISVID, reg, data, mask);
|
|
}
|
|
|
|
static void setsrregmask(SISPtr pSiS, CARD8 reg, CARD8 data, CARD8 mask)
|
|
{
|
|
setSISIDXREGmask(SISSR, reg, data, mask);
|
|
}
|
|
|
|
/* VBlank */
|
|
static CARD8 vblank_active_CRT1(SISPtr pSiS, SISPortPrivPtr pPriv)
|
|
{
|
|
return(inSISREG(SISINPSTAT) & 0x08); /* Verified */
|
|
}
|
|
|
|
static CARD8 vblank_active_CRT2(SISPtr pSiS, SISPortPrivPtr pPriv)
|
|
{
|
|
CARD8 ret;
|
|
|
|
if(pPriv->bridgeIsSlave) return(vblank_active_CRT1(pSiS, pPriv));
|
|
|
|
if(pSiS->VGAEngine == SIS_315_VGA) {
|
|
inSISIDXREG(SISPART1, 0x30, ret);
|
|
} else {
|
|
inSISIDXREG(SISPART1, 0x25, ret);
|
|
}
|
|
return(ret & 0x02); /* Verified */
|
|
}
|
|
|
|
/* Scanline - unused */
|
|
#if 0
|
|
static CARD16 get_scanline_CRT1(SISPtr pSiS)
|
|
{
|
|
CARD32 line;
|
|
|
|
_siswrite(pSiS, REG_PRIM_CRT_COUNTER, 0x00000001);
|
|
line = _sisread(pSiS, REG_PRIM_CRT_COUNTER);
|
|
|
|
return((CARD16)((line >> 16) & 0x07FF));
|
|
}
|
|
#endif
|
|
|
|
static CARD16 get_scanline_CRT2(SISPtr pSiS, SISPortPrivPtr pPriv)
|
|
{
|
|
CARD8 reg1, reg2;
|
|
|
|
if(pSiS->VGAEngine == SIS_315_VGA) {
|
|
inSISIDXREG(SISPART1, 0x32, reg1);
|
|
inSISIDXREG(SISPART1, 0x33, reg2);
|
|
} else {
|
|
inSISIDXREG(SISPART1, 0x27, reg1);
|
|
inSISIDXREG(SISPART1, 0x28, reg2);
|
|
}
|
|
|
|
return((CARD16)(reg1 | ((reg2 & 0x70) << 4)));
|
|
}
|
|
|
|
/* Helper: Count attributes */
|
|
static int
|
|
SiSCountAttributes(XF86AttributeRec *attrs)
|
|
{
|
|
int num = 0;
|
|
|
|
while(attrs[num].name) num++;
|
|
|
|
return num;
|
|
}
|
|
|
|
/*********************************
|
|
* Video gamma *
|
|
*********************************/
|
|
|
|
static void
|
|
SiSComputeXvGamma(SISPtr pSiS)
|
|
{
|
|
int num = 255, i;
|
|
double red = 1.0 / (double)((double)pSiS->XvGammaRed / 1000);
|
|
double green = 1.0 / (double)((double)pSiS->XvGammaGreen / 1000);
|
|
double blue = 1.0 / (double)((double)pSiS->XvGammaBlue / 1000);
|
|
|
|
for(i = 0; i <= num; i++) {
|
|
pSiS->XvGammaRampRed[i] =
|
|
(red == 1.0) ? i : (CARD8)(pow((double)i / (double)num, red) * (double)num + 0.5);
|
|
|
|
pSiS->XvGammaRampGreen[i] =
|
|
(green == 1.0) ? i : (CARD8)(pow((double)i / (double)num, green) * (double)num + 0.5);
|
|
|
|
pSiS->XvGammaRampBlue[i] =
|
|
(blue == 1.0) ? i : (CARD8)(pow((double)i / (double)num, blue) * (double)num + 0.5);
|
|
}
|
|
}
|
|
|
|
static void
|
|
SiSSetXvGamma(SISPtr pSiS)
|
|
{
|
|
int i;
|
|
UChar backup = getsrreg(pSiS, 0x1f);
|
|
setsrregmask(pSiS, 0x1f, 0x08, 0x18);
|
|
for(i = 0; i <= 255; i++) {
|
|
SIS_MMIO_OUT32(pSiS->IOBase, 0x8570,
|
|
(i << 24) |
|
|
(pSiS->XvGammaRampBlue[i] << 16) |
|
|
(pSiS->XvGammaRampGreen[i] << 8) |
|
|
pSiS->XvGammaRampRed[i]);
|
|
}
|
|
setsrregmask(pSiS, 0x1f, backup, 0xff);
|
|
}
|
|
|
|
void
|
|
SiSUpdateXvGamma(SISPtr pSiS, SISPortPrivPtr pPriv)
|
|
{
|
|
UChar sr7 = getsrreg(pSiS, 0x07);
|
|
|
|
if(!pSiS->XvGamma) return;
|
|
if(!(pSiS->MiscFlags & MISC_CRT1OVERLAYGAMMA)) return;
|
|
|
|
#ifdef SISDUALHEAD
|
|
if((pPriv->dualHeadMode) && (!pSiS->SecondHead)) return;
|
|
#endif
|
|
|
|
if(!(sr7 & 0x04)) return;
|
|
|
|
SiSComputeXvGamma(pSiS);
|
|
SiSSetXvGamma(pSiS);
|
|
}
|
|
|
|
static void
|
|
SISResetXvGamma(ScrnInfoPtr pScrn)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);
|
|
|
|
SiSUpdateXvGamma(pSiS, pPriv);
|
|
}
|
|
|
|
/*********************************
|
|
* InitVideo() *
|
|
*********************************/
|
|
|
|
void
|
|
SISInitVideo(ScreenPtr pScreen)
|
|
{
|
|
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
|
|
XF86VideoAdaptorPtr newAdaptor = NULL, newBlitAdaptor = NULL;
|
|
int num_adaptors;
|
|
|
|
newAdaptor = SISSetupImageVideo(pScreen);
|
|
if(newAdaptor) {
|
|
SISInitOffscreenImages(pScreen);
|
|
}
|
|
|
|
#ifdef INCL_YUV_BLIT_ADAPTOR
|
|
if( ( (pSiS->ChipFlags & SiSCF_Is65x) ||
|
|
(pSiS->ChipType >= SIS_330) ) &&
|
|
(pScrn->bitsPerPixel != 8) ) {
|
|
newBlitAdaptor = SISSetupBlitVideo(pScreen);
|
|
}
|
|
#endif
|
|
|
|
num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
|
|
|
|
if(newAdaptor || newBlitAdaptor) {
|
|
int size = num_adaptors;
|
|
|
|
if(newAdaptor) size++;
|
|
if(newBlitAdaptor) size++;
|
|
|
|
newAdaptors = xalloc(size * sizeof(XF86VideoAdaptorPtr*));
|
|
if(newAdaptors) {
|
|
if(num_adaptors) {
|
|
memcpy(newAdaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr));
|
|
}
|
|
if(pSiS->XvDefAdaptorBlit) {
|
|
if(newBlitAdaptor) {
|
|
newAdaptors[num_adaptors] = newBlitAdaptor;
|
|
num_adaptors++;
|
|
}
|
|
}
|
|
if(newAdaptor) {
|
|
newAdaptors[num_adaptors] = newAdaptor;
|
|
num_adaptors++;
|
|
}
|
|
if(!pSiS->XvDefAdaptorBlit) {
|
|
if(newBlitAdaptor) {
|
|
newAdaptors[num_adaptors] = newBlitAdaptor;
|
|
num_adaptors++;
|
|
}
|
|
}
|
|
adaptors = newAdaptors;
|
|
}
|
|
}
|
|
|
|
if(num_adaptors) {
|
|
xf86XVScreenInit(pScreen, adaptors, num_adaptors);
|
|
}
|
|
|
|
if(newAdaptors) {
|
|
xfree(newAdaptors);
|
|
}
|
|
}
|
|
|
|
/*********************************
|
|
* SetPortsDefault() *
|
|
*********************************/
|
|
|
|
void
|
|
SISSetPortDefaults(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
#ifdef SISDUALHEAD
|
|
SISEntPtr pSiSEnt = pSiS->entityPrivate;;
|
|
#endif
|
|
|
|
pPriv->colorKey = pSiS->colorKey = 0x000101fe;
|
|
pPriv->brightness = pSiS->XvDefBri;
|
|
pPriv->contrast = pSiS->XvDefCon;
|
|
pPriv->hue = pSiS->XvDefHue;
|
|
pPriv->saturation = pSiS->XvDefSat;
|
|
pPriv->autopaintColorKey = TRUE;
|
|
pPriv->disablegfx = pSiS->XvDefDisableGfx;
|
|
pPriv->disablegfxlr= pSiS->XvDefDisableGfxLR;
|
|
pSiS->disablecolorkeycurrent = pSiS->XvDisableColorKey;
|
|
pPriv->usechromakey = pSiS->XvUseChromaKey;
|
|
pPriv->insidechromakey = pSiS->XvInsideChromaKey;
|
|
pPriv->yuvchromakey = pSiS->XvYUVChromaKey;
|
|
pPriv->chromamin = pSiS->XvChromaMin;
|
|
pPriv->chromamax = pSiS->XvChromaMax;
|
|
if(pPriv->dualHeadMode) {
|
|
#ifdef SISDUALHEAD
|
|
if(!pSiS->SecondHead) {
|
|
pPriv->tvxpos = pSiS->tvxpos;
|
|
pPriv->tvypos = pSiS->tvypos;
|
|
pPriv->updatetvxpos = TRUE;
|
|
pPriv->updatetvypos = TRUE;
|
|
}
|
|
#endif
|
|
} else {
|
|
pPriv->tvxpos = pSiS->tvxpos;
|
|
pPriv->tvypos = pSiS->tvypos;
|
|
pPriv->updatetvxpos = TRUE;
|
|
pPriv->updatetvypos = TRUE;
|
|
}
|
|
#ifdef SIS_CP
|
|
SIS_CP_VIDEO_DEF
|
|
#endif
|
|
if(pPriv->dualHeadMode) {
|
|
#ifdef SISDUALHEAD
|
|
pPriv->crtnum =
|
|
pSiSEnt->curxvcrtnum =
|
|
pSiSEnt->XvOnCRT2 ? 1 : 0;
|
|
#endif
|
|
} else
|
|
pPriv->crtnum = pSiS->XvOnCRT2 ? 1 : 0;
|
|
|
|
pSiS->XvGammaRed = pSiS->XvGammaRedDef;
|
|
pSiS->XvGammaGreen = pSiS->XvGammaGreenDef;
|
|
pSiS->XvGammaBlue = pSiS->XvGammaBlueDef;
|
|
SiSUpdateXvGamma(pSiS, pPriv);
|
|
}
|
|
|
|
/*********************************
|
|
* ResetVideo() *
|
|
*********************************/
|
|
|
|
static void
|
|
SISResetVideo(ScrnInfoPtr pScrn)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);
|
|
|
|
/* Unlock registers */
|
|
#ifdef UNLOCK_ALWAYS
|
|
sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL);
|
|
#endif
|
|
if(getvideoreg (pSiS, Index_VI_Passwd) != 0xa1) {
|
|
setvideoreg (pSiS, Index_VI_Passwd, 0x86);
|
|
if(getvideoreg (pSiS, Index_VI_Passwd) != 0xa1)
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
|
"Xv: Video password could not unlock registers\n");
|
|
}
|
|
|
|
/* Initialize first overlay (CRT1) ------------------------------- */
|
|
|
|
/* This bit has obviously a different meaning on 315 series (linebuffer-related) */
|
|
if(pSiS->VGAEngine == SIS_300_VGA) {
|
|
/* Write-enable video registers */
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x80, 0x81);
|
|
} else {
|
|
/* Select overlay 2, clear all linebuffer related bits */
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0xb1);
|
|
}
|
|
|
|
/* Disable overlay */
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02);
|
|
|
|
/* Disable bob de-interlacer and some strange bit */
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x82);
|
|
|
|
/* Select RGB chroma key format (300 series only) */
|
|
if(pSiS->VGAEngine == SIS_300_VGA) {
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x40);
|
|
}
|
|
|
|
/* Reset scale control and contrast */
|
|
/* (Enable DDA (interpolation)) */
|
|
setvideoregmask(pSiS, Index_VI_Scale_Control, 0x60, 0x60);
|
|
setvideoregmask(pSiS, Index_VI_Contrast_Enh_Ctrl, 0x04, 0x1F);
|
|
|
|
setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Preset_Low, 0x00);
|
|
setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Preset_Middle, 0x00);
|
|
setvideoreg(pSiS, Index_VI_UV_Buf_Preset_Low, 0x00);
|
|
setvideoreg(pSiS, Index_VI_UV_Buf_Preset_Middle, 0x00);
|
|
setvideoreg(pSiS, Index_VI_Disp_Y_UV_Buf_Preset_High, 0x00);
|
|
setvideoreg(pSiS, Index_VI_Play_Threshold_Low, 0x00);
|
|
setvideoreg(pSiS, Index_VI_Play_Threshold_High, 0x00);
|
|
if(pSiS->Chipset == PCI_CHIP_SIS330) {
|
|
/* Disable contrast enhancement (?) */
|
|
setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x00, 0x10);
|
|
} else if(pPriv->is661741760) {
|
|
setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x00, 0xE0);
|
|
if(pPriv->is760) {
|
|
setvideoregmask(pSiS, Index_VI_V_Buf_Start_Over, 0x3c, 0x3c);
|
|
} else { /* 661, 741 */
|
|
setvideoregmask(pSiS, Index_VI_V_Buf_Start_Over, 0x2c, 0x3c);
|
|
}
|
|
} else if((pSiS->Chipset == PCI_CHIP_SIS340) ||
|
|
(pSiS->Chipset == PCI_CHIP_XGIXG20) ||
|
|
(pSiS->Chipset == PCI_CHIP_XGIXG40)) {
|
|
/* Disable contrast enhancement (?) */
|
|
setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x00, 0x10);
|
|
/* Threshold high */
|
|
setvideoregmask(pSiS, 0xb5, 0x00, 0x01);
|
|
setvideoregmask(pSiS, 0xb6, 0x00, 0x01);
|
|
/* Enable horizontal, disable vertical 4-tap DDA scaler */
|
|
setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x40, 0xc0);
|
|
set_dda_regs(pSiS, 1.0);
|
|
/* Enable software-flip */
|
|
setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x20, 0x20);
|
|
/* "Disable video processor" */
|
|
setsrregmask(pSiS, 0x3f, 0x00, 0x02);
|
|
} else if(pPriv->is761) {
|
|
/* Disable contrast enhancement (?) */
|
|
setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x00, 0x10);
|
|
/* Threshold high */
|
|
setvideoregmask(pSiS, 0xb5, 0x00, 0x01);
|
|
setvideoregmask(pSiS, 0xb6, 0x00, 0x01);
|
|
/* Enable horizontal, disable vertical 4-tap DDA scaler */
|
|
setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x40, 0xC0);
|
|
/* ? */
|
|
setvideoregmask(pSiS, 0xb6, 0x02, 0x02);
|
|
set_dda_regs(pSiS, 1.0);
|
|
setvideoregmask(pSiS, Index_VI_V_Buf_Start_Over, 0x00, 0x3c);
|
|
}
|
|
|
|
if((pSiS->ChipFlags & SiSCF_Is65x) || (pPriv->is661741760)) {
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0x04);
|
|
}
|
|
|
|
/* Reset top window position for scanline check */
|
|
setvideoreg(pSiS, Index_VI_Win_Ver_Disp_Start_Low, 0x00);
|
|
setvideoreg(pSiS, Index_VI_Win_Ver_Over, 0x00);
|
|
|
|
/* Initialize second overlay (CRT2) - only for 300, 630/730, 550, M650/651, 661/741/660/760 */
|
|
if(pSiS->hasTwoOverlays) {
|
|
|
|
if(pSiS->VGAEngine == SIS_300_VGA) {
|
|
/* Write-enable video registers */
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x81, 0x81);
|
|
} else {
|
|
/* Select overlay 2, clear all linebuffer related bits */
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, 0xb1);
|
|
}
|
|
|
|
/* Disable overlay */
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02);
|
|
|
|
/* Disable bob de-interlacer and some strange bit */
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x82);
|
|
|
|
/* Select RGB chroma key format */
|
|
if(pSiS->VGAEngine == SIS_300_VGA) {
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x40);
|
|
}
|
|
|
|
/* Reset scale control and contrast */
|
|
/* (Enable DDA (interpolation)) */
|
|
setvideoregmask(pSiS, Index_VI_Scale_Control, 0x60, 0x60);
|
|
setvideoregmask(pSiS, Index_VI_Contrast_Enh_Ctrl, 0x04, 0x1F);
|
|
|
|
setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Preset_Low, 0x00);
|
|
setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Preset_Middle, 0x00);
|
|
setvideoreg(pSiS, Index_VI_UV_Buf_Preset_Low, 0x00);
|
|
setvideoreg(pSiS, Index_VI_UV_Buf_Preset_Middle, 0x00);
|
|
setvideoreg(pSiS, Index_VI_Disp_Y_UV_Buf_Preset_High, 0x00);
|
|
setvideoreg(pSiS, Index_VI_Play_Threshold_Low, 0x00);
|
|
setvideoreg(pSiS, Index_VI_Play_Threshold_High, 0x00);
|
|
|
|
if(pPriv->is661741760) {
|
|
CARD8 temp;
|
|
setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x00, 0xE0);
|
|
switch(pSiS->ChipType) {
|
|
case SIS_661: temp = 0x24; break;
|
|
case SIS_741: temp = 0x2c; break;
|
|
default: temp = 0x3c;
|
|
}
|
|
setvideoregmask(pSiS, Index_VI_V_Buf_Start_Over, temp, 0x3c);
|
|
} else if(pPriv->is761) {
|
|
setvideoregmask(pSiS, Index_VI_V_Buf_Start_Over, 0x00, 0x3c);
|
|
} else if(pSiS->Chipset == PCI_CHIP_SIS340) { /* 2 overlays? */
|
|
setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x00, 0x10);
|
|
setvideoregmask(pSiS, 0xb5, 0x00, 0x01);
|
|
setvideoregmask(pSiS, 0xb6, 0x00, 0x01);
|
|
setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x40, 0xC0);
|
|
set_dda_regs(pSiS, 1.0);
|
|
setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x20, 0x20);
|
|
}
|
|
|
|
setvideoreg(pSiS, Index_VI_Win_Ver_Disp_Start_Low, 0x00);
|
|
setvideoreg(pSiS, Index_VI_Win_Ver_Over, 0x00);
|
|
|
|
}
|
|
|
|
/* set default properties for overlay 1 (CRT1) -------------------------- */
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0x01);
|
|
setvideoregmask(pSiS, Index_VI_Contrast_Enh_Ctrl, 0x04, 0x07);
|
|
setvideoreg(pSiS, Index_VI_Brightness, 0x20);
|
|
if(pSiS->VGAEngine == SIS_315_VGA) {
|
|
setvideoreg(pSiS, Index_VI_Hue, 0x00);
|
|
setvideoreg(pSiS, Index_VI_Saturation, 0x00);
|
|
}
|
|
|
|
/* set default properties for overlay 2(CRT2) -------------------------- */
|
|
if(pSiS->hasTwoOverlays) {
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, 0x01);
|
|
setvideoregmask(pSiS, Index_VI_Contrast_Enh_Ctrl, 0x04, 0x07);
|
|
setvideoreg(pSiS, Index_VI_Brightness, 0x20);
|
|
if(pSiS->VGAEngine == SIS_315_VGA) {
|
|
setvideoreg(pSiS, Index_VI_Hue, 0x00);
|
|
setvideoreg(pSiS, Index_VI_Saturation, 0x00);
|
|
}
|
|
}
|
|
|
|
/* Reset Xv gamma correction */
|
|
if(pSiS->VGAEngine == SIS_315_VGA) {
|
|
SiSUpdateXvGamma(pSiS, pPriv);
|
|
}
|
|
|
|
pPriv->mustresettap = TRUE;
|
|
#ifdef SISMERGED
|
|
pPriv->mustresettap2 = TRUE;
|
|
#endif
|
|
}
|
|
|
|
/*********************************
|
|
* Set displaymode *
|
|
*********************************/
|
|
|
|
/* Set display mode (single CRT1/CRT2, mirror).
|
|
* MIRROR mode is only available on chipsets with two overlays.
|
|
* On the other chipsets, if only CRT1 or only CRT2 are used,
|
|
* the correct display CRT is chosen automatically. If both
|
|
* CRT1 and CRT2 are connected, the user can choose between CRT1 and
|
|
* CRT2 by using the option XvOnCRT2.
|
|
*/
|
|
|
|
static void
|
|
set_dispmode(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
|
|
pPriv->dualHeadMode = pPriv->bridgeIsSlave = FALSE;
|
|
|
|
if(SiSBridgeIsInSlaveMode(pScrn)) {
|
|
pPriv->bridgeIsSlave = TRUE;
|
|
}
|
|
|
|
if( (pSiS->VBFlags & VB_DISPMODE_MIRROR) ||
|
|
((pPriv->bridgeIsSlave) && (pSiS->VBFlags & DISPTYPE_DISP2)) ) {
|
|
if(pPriv->hasTwoOverlays)
|
|
pPriv->displayMode = DISPMODE_MIRROR; /* CRT1+CRT2 (2 overlays) */
|
|
else if(pPriv->crtnum)
|
|
pPriv->displayMode = DISPMODE_SINGLE2; /* CRT2 only */
|
|
else
|
|
pPriv->displayMode = DISPMODE_SINGLE1; /* CRT1 only */
|
|
} else {
|
|
#ifdef SISDUALHEAD
|
|
if(pSiS->DualHeadMode) {
|
|
pPriv->dualHeadMode = TRUE;
|
|
if(pSiS->SecondHead)
|
|
pPriv->displayMode = DISPMODE_SINGLE1; /* CRT1 only */
|
|
else
|
|
pPriv->displayMode = DISPMODE_SINGLE2; /* CRT2 only */
|
|
} else
|
|
#endif
|
|
if(pSiS->VBFlags & DISPTYPE_DISP1) {
|
|
pPriv->displayMode = DISPMODE_SINGLE1; /* CRT1 only */
|
|
} else {
|
|
pPriv->displayMode = DISPMODE_SINGLE2; /* CRT2 only */
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
set_disptype_regs(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
#ifdef SISDUALHEAD
|
|
SISEntPtr pSiSEnt = pSiS->entityPrivate;
|
|
int crtnum = 0;
|
|
|
|
if(pPriv->dualHeadMode) crtnum = pSiSEnt->curxvcrtnum;
|
|
#endif
|
|
|
|
/*
|
|
* SR06[7:6]
|
|
* Bit 7: Enable overlay 1 on CRT2
|
|
* Bit 6: Enable overlay 0 on CRT2
|
|
* SR32[7:6]
|
|
* Bit 7: DCLK/TCLK overlay 1
|
|
* 0=DCLK (overlay on CRT1)
|
|
* 1=TCLK (overlay on CRT2)
|
|
* Bit 6: DCLK/TCLK overlay 0
|
|
* 0=DCLK (overlay on CRT1)
|
|
* 1=TCLK (overlay on CRT2)
|
|
*
|
|
* On chipsets with two overlays, we can freely select and also
|
|
* have a mirror mode. However, we use overlay 0 for CRT1 and
|
|
* overlay 1 for CRT2.
|
|
* ATTENTION: CRT2 can only take up to 1 (one) overlay. Setting
|
|
* SR06/32 to 0xc0 DOES NOT WORK. THAT'S CONFIRMED.
|
|
* Therefore, we use overlay 0 on CRT2 if in SINGLE2 mode.
|
|
*
|
|
* For chipsets with only one overlay, user must choose whether
|
|
* to display the overlay on CRT1 or CRT2 by setting XvOnCRT2
|
|
* to TRUE (CRT2) or FALSE (CRT1). The driver does this auto-
|
|
* matically if only CRT1 or only CRT2 is used.
|
|
*/
|
|
#ifdef UNLOCK_ALWAYS
|
|
sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL);
|
|
#endif
|
|
|
|
switch (pPriv->displayMode)
|
|
{
|
|
case DISPMODE_SINGLE1: /* CRT1-only mode: */
|
|
if(pPriv->hasTwoOverlays) {
|
|
if(pPriv->dualHeadMode) {
|
|
setsrregmask(pSiS, 0x06, 0x00, 0x40); /* overlay 0 -> CRT1 */
|
|
setsrregmask(pSiS, 0x32, 0x00, 0x40);
|
|
} else {
|
|
setsrregmask(pSiS, 0x06, 0x00, 0xc0); /* both overlays -> CRT1 */
|
|
setsrregmask(pSiS, 0x32, 0x00, 0xc0);
|
|
}
|
|
} else {
|
|
#ifdef SISDUALHEAD
|
|
if((!pPriv->dualHeadMode) || (crtnum == 0)) {
|
|
#endif
|
|
setsrregmask(pSiS, 0x06, 0x00, 0xc0); /* only overlay -> CRT1 */
|
|
setsrregmask(pSiS, 0x32, 0x00, 0xc0);
|
|
#ifdef SISDUALHEAD
|
|
}
|
|
#endif
|
|
}
|
|
break;
|
|
|
|
case DISPMODE_SINGLE2: /* CRT2-only mode: */
|
|
if(pPriv->hasTwoOverlays) {
|
|
if(pPriv->dualHeadMode) {
|
|
setsrregmask(pSiS, 0x06, 0x80, 0x80); /* overlay 1 -> CRT2 */
|
|
setsrregmask(pSiS, 0x32, 0x80, 0x80);
|
|
} else {
|
|
setsrregmask(pSiS, 0x06, 0x40, 0xc0); /* overlay 0 -> CRT2 */
|
|
setsrregmask(pSiS, 0x32, 0xc0, 0xc0); /* (although both clocks for CRT2!) */
|
|
}
|
|
} else {
|
|
#ifdef SISDUALHEAD
|
|
if((!pPriv->dualHeadMode) || (crtnum == 1)) {
|
|
#endif
|
|
if(pSiS->MiscFlags & MISC_SIS760ONEOVERLAY) {
|
|
setsrregmask(pSiS, 0x06, 0x40, 0xc0); /* overlay 0 -> CRT2 */
|
|
setsrregmask(pSiS, 0x32, 0xc0, 0xc0); /* (although both clocks for CRT2!) */
|
|
} else {
|
|
setsrregmask(pSiS, 0x06, 0x40, 0xc0); /* only overlay -> CRT2 */
|
|
setsrregmask(pSiS, 0x32, 0x40, 0xc0);
|
|
}
|
|
#ifdef SISDUALHEAD
|
|
}
|
|
#endif
|
|
}
|
|
break;
|
|
|
|
case DISPMODE_MIRROR: /* CRT1+CRT2-mode: (only on chips with 2 overlays) */
|
|
default:
|
|
setsrregmask(pSiS, 0x06, 0x80, 0xc0); /* overlay 0 -> CRT1, overlay 1 -> CRT2 */
|
|
setsrregmask(pSiS, 0x32, 0x80, 0xc0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
set_hastwooverlays(SISPtr pSiS, SISPortPrivPtr pPriv)
|
|
{
|
|
int temp, watchdog;
|
|
|
|
if(pSiS->hasTwoOverlays) {
|
|
if(pSiS->MiscFlags & MISC_SIS760ONEOVERLAY) {
|
|
if(pPriv->hasTwoOverlays) {
|
|
/* Disable overlay 1 on change */
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, 0x01);
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x01);
|
|
temp = getvideoreg(pSiS,Index_VI_Control_Misc0);
|
|
if(temp & 0x02) {
|
|
watchdog = WATCHDOG_DELAY;
|
|
while((!vblank_active_CRT2(pSiS, pPriv)) && --watchdog);
|
|
watchdog = WATCHDOG_DELAY;
|
|
while(vblank_active_CRT2(pSiS, pPriv) && --watchdog);
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02);
|
|
}
|
|
}
|
|
pPriv->hasTwoOverlays = FALSE;
|
|
} else {
|
|
pPriv->hasTwoOverlays = TRUE;
|
|
}
|
|
} else {
|
|
pPriv->hasTwoOverlays = FALSE;
|
|
}
|
|
}
|
|
|
|
static void
|
|
set_allowswitchcrt(SISPtr pSiS, SISPortPrivPtr pPriv)
|
|
{
|
|
if(pPriv->hasTwoOverlays) {
|
|
pPriv->AllowSwitchCRT = FALSE;
|
|
} else if((!(pSiS->VBFlags & DISPTYPE_DISP1)) || (!(pSiS->VBFlags & DISPTYPE_DISP2))) {
|
|
pPriv->AllowSwitchCRT = FALSE;
|
|
if(!(pSiS->VBFlags & DISPTYPE_DISP1)) pPriv->crtnum = 1;
|
|
else pPriv->crtnum = 0;
|
|
} else {
|
|
pPriv->AllowSwitchCRT = TRUE;
|
|
}
|
|
}
|
|
|
|
static void
|
|
set_maxencoding(SISPtr pSiS, SISPortPrivPtr pPriv)
|
|
{
|
|
int half;
|
|
|
|
if(pSiS->VGAEngine == SIS_300_VGA) {
|
|
DummyEncoding.width = IMAGE_MAX_WIDTH_300;
|
|
DummyEncoding.height = IMAGE_MAX_HEIGHT_300;
|
|
} else {
|
|
DummyEncoding.width = IMAGE_MAX_WIDTH_315;
|
|
DummyEncoding.height = IMAGE_MAX_HEIGHT_315;
|
|
half = IMAGE_MAX_WIDTH_315 >> 1;
|
|
if(pPriv->is661741760) {
|
|
half = 768 * 2;
|
|
} else if(pPriv->is340) { /* 2 overlays? */
|
|
DummyEncoding.width = IMAGE_MAX_WIDTH_340;
|
|
half = 1280; /* ? */
|
|
} else if(pPriv->is761) {
|
|
DummyEncoding.width = IMAGE_MAX_WIDTH_761;
|
|
half = 1920; /* ? */
|
|
}
|
|
if(pPriv->hasTwoOverlays) {
|
|
#ifdef SISDUALHEAD
|
|
if(pSiS->DualHeadMode) {
|
|
DummyEncoding.width = half;
|
|
} else
|
|
#endif
|
|
#ifdef SISMERGED
|
|
if(pSiS->MergedFB) {
|
|
DummyEncoding.width = half;
|
|
} else
|
|
#endif
|
|
if(pPriv->displayMode == DISPMODE_MIRROR) {
|
|
DummyEncoding.width = half;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*********************************
|
|
* ResetXvDisplay() *
|
|
*********************************/
|
|
|
|
static void
|
|
SISResetXvDisplay(ScrnInfoPtr pScrn)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);
|
|
|
|
if(!pPriv) return;
|
|
|
|
set_hastwooverlays(pSiS, pPriv);
|
|
set_allowswitchcrt(pSiS, pPriv);
|
|
set_dispmode(pScrn, pPriv);
|
|
set_maxencoding(pSiS, pPriv);
|
|
}
|
|
|
|
/*********************************
|
|
* SetupImageVideo() *
|
|
*********************************/
|
|
|
|
static XF86VideoAdaptorPtr
|
|
SISSetupImageVideo(ScreenPtr pScreen)
|
|
{
|
|
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
XF86VideoAdaptorPtr adapt;
|
|
SISPortPrivPtr pPriv;
|
|
|
|
#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,1,99,1,0)
|
|
XAAInfoRecPtr pXAA = pSiS->AccelInfoPtr;
|
|
|
|
if(!pXAA || !pXAA->FillSolidRects) {
|
|
return NULL;
|
|
}
|
|
#endif
|
|
|
|
if(!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
|
|
sizeof(SISPortPrivRec) +
|
|
sizeof(DevUnion)))) {
|
|
return NULL;
|
|
}
|
|
|
|
adapt->type = XvWindowMask | XvInputMask | XvImageMask;
|
|
adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
|
|
adapt->name = "SIS 300/315/330 series Video Overlay";
|
|
adapt->nEncodings = 1;
|
|
adapt->pEncodings = &DummyEncoding;
|
|
|
|
adapt->nFormats = NUM_FORMATS;
|
|
adapt->pFormats = SISFormats;
|
|
adapt->nPorts = 1;
|
|
adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
|
|
|
|
pPriv = (SISPortPrivPtr)(&adapt->pPortPrivates[1]);
|
|
|
|
pPriv->videoStatus = 0;
|
|
pPriv->currentBuf = 0;
|
|
pPriv->handle = NULL;
|
|
pPriv->grabbedByV4L= FALSE;
|
|
pPriv->NoOverlay = FALSE;
|
|
pPriv->PrevOverlay = FALSE;
|
|
pPriv->is661741760 = ((pSiS->ChipType >= SIS_661) &&
|
|
(pSiS->ChipType <= SIS_760)) ? TRUE : FALSE;
|
|
pPriv->is760 = (pSiS->ChipType == SIS_760) ? TRUE : FALSE;
|
|
pPriv->is761 = (pSiS->ChipType == SIS_761) ? TRUE : FALSE;
|
|
pPriv->is340 = (pSiS->Chipset == PCI_CHIP_SIS340) ? TRUE : FALSE;
|
|
pPriv->isXGI = (pSiS->Chipset == PCI_CHIP_XGIXG20 ||
|
|
pSiS->Chipset == PCI_CHIP_XGIXG40) ? TRUE : FALSE;
|
|
|
|
/* Setup chipset type helpers */
|
|
set_hastwooverlays(pSiS, pPriv);
|
|
set_allowswitchcrt(pSiS, pPriv);
|
|
|
|
pPriv->havetapscaler = FALSE;
|
|
if(pPriv->is340 || pPriv->is761 || pPriv->isXGI) {
|
|
pPriv->havetapscaler = TRUE;
|
|
}
|
|
|
|
adapt->pPortPrivates[0].ptr = (pointer)(pPriv);
|
|
if(pSiS->VGAEngine == SIS_300_VGA) {
|
|
adapt->nImages = NUM_IMAGES_300;
|
|
adapt->pAttributes = SISAttributes_300;
|
|
adapt->nAttributes = SiSCountAttributes(&SISAttributes_300[0]);
|
|
} else {
|
|
if(pSiS->ChipType >= SIS_330) {
|
|
adapt->nImages = NUM_IMAGES_330;
|
|
} else {
|
|
adapt->nImages = NUM_IMAGES_315;
|
|
}
|
|
adapt->pAttributes = SISAttributes_315;
|
|
adapt->nAttributes = SiSCountAttributes(&SISAttributes_315[0]);
|
|
if((pSiS->hasTwoOverlays) && (!(pSiS->SiS_SD2_Flags & SiS_SD2_SUPPORT760OO))) {
|
|
adapt->nAttributes--;
|
|
}
|
|
}
|
|
|
|
adapt->pImages = SISImages;
|
|
adapt->PutVideo = NULL;
|
|
adapt->PutStill = NULL;
|
|
adapt->GetVideo = NULL;
|
|
adapt->GetStill = NULL;
|
|
adapt->StopVideo = SISStopVideo;
|
|
adapt->SetPortAttribute = SISSetPortAttribute;
|
|
adapt->GetPortAttribute = SISGetPortAttribute;
|
|
adapt->QueryBestSize = SISQueryBestSize;
|
|
adapt->PutImage = SISPutImage;
|
|
adapt->QueryImageAttributes = SISQueryImageAttributes;
|
|
|
|
/* gotta uninit this someplace */
|
|
#if defined(REGION_NULL)
|
|
REGION_NULL(pScreen, &pPriv->clip);
|
|
#else
|
|
REGION_INIT(pScreen, &pPriv->clip, NullBox, 0);
|
|
#endif
|
|
|
|
pSiS->adaptor = adapt;
|
|
|
|
pSiS->xvBrightness = MAKE_ATOM(sisxvbrightness);
|
|
pSiS->xvContrast = MAKE_ATOM(sisxvcontrast);
|
|
pSiS->xvColorKey = MAKE_ATOM(sisxvcolorkey);
|
|
pSiS->xvSaturation = MAKE_ATOM(sisxvsaturation);
|
|
pSiS->xvHue = MAKE_ATOM(sisxvhue);
|
|
pSiS->xvSwitchCRT = MAKE_ATOM(sisxvswitchcrt);
|
|
pSiS->xvAutopaintColorKey = MAKE_ATOM(sisxvautopaintcolorkey);
|
|
pSiS->xvSetDefaults = MAKE_ATOM(sisxvsetdefaults);
|
|
pSiS->xvDisableGfx = MAKE_ATOM(sisxvdisablegfx);
|
|
pSiS->xvDisableGfxLR = MAKE_ATOM(sisxvdisablegfxlr);
|
|
pSiS->xvTVXPosition = MAKE_ATOM(sisxvtvxposition);
|
|
pSiS->xvTVYPosition = MAKE_ATOM(sisxvtvyposition);
|
|
pSiS->xvGammaRed = MAKE_ATOM(sisxvgammared);
|
|
pSiS->xvGammaGreen = MAKE_ATOM(sisxvgammagreen);
|
|
pSiS->xvGammaBlue = MAKE_ATOM(sisxvgammablue);
|
|
pSiS->xvDisableColorkey = MAKE_ATOM(sisxvdisablecolorkey);
|
|
pSiS->xvUseChromakey = MAKE_ATOM(sisxvusechromakey);
|
|
pSiS->xvInsideChromakey = MAKE_ATOM(sisxvinsidechromakey);
|
|
pSiS->xvYUVChromakey = MAKE_ATOM(sisxvyuvchromakey);
|
|
pSiS->xvChromaMin = MAKE_ATOM(sisxvchromamin);
|
|
pSiS->xvChromaMax = MAKE_ATOM(sisxvchromamax);
|
|
#ifdef SISDEINT
|
|
pSiS->xvdeintmeth = MAKE_ATOM(sisxvdeinterlace);
|
|
#endif
|
|
#ifdef XV_SD_DEPRECATED
|
|
pSiS->xv_QVF = MAKE_ATOM(sisxvqueryvbflags);
|
|
pSiS->xv_GDV = MAKE_ATOM(sisxvsdgetdriverversion);
|
|
pSiS->xv_GHI = MAKE_ATOM(sisxvsdgethardwareinfo);
|
|
pSiS->xv_GBI = MAKE_ATOM(sisxvsdgetbusid);
|
|
pSiS->xv_QVV = MAKE_ATOM(sisxvsdqueryvbflagsversion);
|
|
pSiS->xv_GSF = MAKE_ATOM(sisxvsdgetsdflags);
|
|
pSiS->xv_GSF2 = MAKE_ATOM(sisxvsdgetsdflags2);
|
|
pSiS->xv_USD = MAKE_ATOM(sisxvsdunlocksisdirect);
|
|
pSiS->xv_SVF = MAKE_ATOM(sisxvsdsetvbflags);
|
|
pSiS->xv_QDD = MAKE_ATOM(sisxvsdquerydetecteddevices);
|
|
pSiS->xv_CT1 = MAKE_ATOM(sisxvsdcrt1status);
|
|
pSiS->xv_CMD = MAKE_ATOM(sisxvsdcheckmodeindexforcrt2);
|
|
pSiS->xv_CMDR = MAKE_ATOM(sisxvsdresultcheckmodeindexforcrt2);
|
|
pSiS->xv_RDT = MAKE_ATOM(sisxvsdredetectcrt2);
|
|
pSiS->xv_TAF = MAKE_ATOM(sisxvsdsisantiflicker);
|
|
pSiS->xv_TSA = MAKE_ATOM(sisxvsdsissaturation);
|
|
pSiS->xv_TEE = MAKE_ATOM(sisxvsdsisedgeenhance);
|
|
pSiS->xv_COC = MAKE_ATOM(sisxvsdsiscolcalibc);
|
|
pSiS->xv_COF = MAKE_ATOM(sisxvsdsiscolcalibf);
|
|
pSiS->xv_CFI = MAKE_ATOM(sisxvsdsiscfilter);
|
|
pSiS->xv_YFI = MAKE_ATOM(sisxvsdsisyfilter);
|
|
pSiS->xv_TCO = MAKE_ATOM(sisxvsdchcontrast);
|
|
pSiS->xv_TTE = MAKE_ATOM(sisxvsdchtextenhance);
|
|
pSiS->xv_TCF = MAKE_ATOM(sisxvsdchchromaflickerfilter);
|
|
pSiS->xv_TLF = MAKE_ATOM(sisxvsdchlumaflickerfilter);
|
|
pSiS->xv_TCC = MAKE_ATOM(sisxvsdchcvbscolor);
|
|
pSiS->xv_OVR = MAKE_ATOM(sisxvsdchoverscan);
|
|
pSiS->xv_SGA = MAKE_ATOM(sisxvsdenablegamma);
|
|
pSiS->xv_TXS = MAKE_ATOM(sisxvsdtvxscale);
|
|
pSiS->xv_TYS = MAKE_ATOM(sisxvsdtvyscale);
|
|
pSiS->xv_GSS = MAKE_ATOM(sisxvsdgetscreensize);
|
|
pSiS->xv_BRR = MAKE_ATOM(sisxvsdstorebrir);
|
|
pSiS->xv_BRG = MAKE_ATOM(sisxvsdstorebrig);
|
|
pSiS->xv_BRB = MAKE_ATOM(sisxvsdstorebrib);
|
|
pSiS->xv_PBR = MAKE_ATOM(sisxvsdstorepbrir);
|
|
pSiS->xv_PBG = MAKE_ATOM(sisxvsdstorepbrig);
|
|
pSiS->xv_PBB = MAKE_ATOM(sisxvsdstorepbrib);
|
|
pSiS->xv_BRR2 = MAKE_ATOM(sisxvsdstorebrir2);
|
|
pSiS->xv_BRG2 = MAKE_ATOM(sisxvsdstorebrig2);
|
|
pSiS->xv_BRB2 = MAKE_ATOM(sisxvsdstorebrib2);
|
|
pSiS->xv_PBR2 = MAKE_ATOM(sisxvsdstorepbrir2);
|
|
pSiS->xv_PBG2 = MAKE_ATOM(sisxvsdstorepbrig2);
|
|
pSiS->xv_PBB2 = MAKE_ATOM(sisxvsdstorepbrib2);
|
|
pSiS->xv_GARC2 = MAKE_ATOM(sisxvsdstoregarc2);
|
|
pSiS->xv_GAGC2 = MAKE_ATOM(sisxvsdstoregagc2);
|
|
pSiS->xv_GABC2 = MAKE_ATOM(sisxvsdstoregabc2);
|
|
pSiS->xv_BRRC2 = MAKE_ATOM(sisxvsdstorebrirc2);
|
|
pSiS->xv_BRGC2 = MAKE_ATOM(sisxvsdstorebrigc2);
|
|
pSiS->xv_BRBC2 = MAKE_ATOM(sisxvsdstorebribc2);
|
|
pSiS->xv_PBRC2 = MAKE_ATOM(sisxvsdstorepbrirc2);
|
|
pSiS->xv_PBGC2 = MAKE_ATOM(sisxvsdstorepbrigc2);
|
|
pSiS->xv_PBBC2 = MAKE_ATOM(sisxvsdstorepbribc2);
|
|
pSiS->xv_SHC = MAKE_ATOM(sisxvsdhidehwcursor);
|
|
pSiS->xv_PMD = MAKE_ATOM(sisxvsdpanelmode);
|
|
#ifdef TWDEBUG
|
|
pSiS->xv_STR = MAKE_ATOM(sisxvsetreg);
|
|
#endif
|
|
#endif /* XV_SD_DEPRECATED */
|
|
#ifdef SIS_CP
|
|
SIS_CP_VIDEO_ATOMS
|
|
#endif
|
|
|
|
pSiS->xv_sisdirectunlocked = 0;
|
|
#ifdef XV_SD_DEPRECATED
|
|
pSiS->xv_sd_result = 0;
|
|
#endif
|
|
|
|
/* 300 series require double words for addresses and pitches,
|
|
* 315/330 series require word.
|
|
*/
|
|
switch (pSiS->VGAEngine) {
|
|
case SIS_315_VGA:
|
|
pPriv->shiftValue = 1;
|
|
break;
|
|
case SIS_300_VGA:
|
|
default:
|
|
pPriv->shiftValue = 2;
|
|
break;
|
|
}
|
|
|
|
/* Set displayMode according to VBFlags */
|
|
set_dispmode(pScrn, pPriv);
|
|
|
|
/* Now for the linebuffer stuff.
|
|
* All chipsets have a certain number of linebuffers, each of a certain
|
|
* size. The number of buffers is per overlay.
|
|
* Chip number size max video size
|
|
* 300 2 ? 720x576
|
|
* 630/730 2 ? 720x576
|
|
* 315 2 960? 1920x1080
|
|
* 550 2? 960? 1920x1080?
|
|
* 650/740 2 960 ("120x128") 1920x1080
|
|
* M650/651.. 4 480 1920x1080
|
|
* 330 2 960 1920x1080
|
|
* 661/741/760 4 768 1920x1080
|
|
* 340 4 1280? 1920x1080?
|
|
* 761 4 1536? 1920x1080?
|
|
* The unit of size is unknown; I just know that a size of 480 limits
|
|
* the video source width to 384. Beyond that, line buffers must be
|
|
* merged (otherwise the video output is garbled).
|
|
* To use the maximum width (eg 1920x1080 on the 315 series, including
|
|
* the M650, 651 and later), *all* line buffers must be merged. Hence,
|
|
* we can only use one overlay. This should be set up for modes where
|
|
* either only CRT1 or only CRT2 is used.
|
|
* If both overlays are going to be used (such as in modes were both
|
|
* CRT1 and CRT2 are active), we are limited to the half of the
|
|
* maximum width, or 1536 on 661/741/760.
|
|
* There is a known hardware problem with the 760 and 761 if the video
|
|
* data is in the UMA area: The memory access latency is too big to
|
|
* allow two overlays under some circumstances. Therefore, we must
|
|
* support switching between hasTwoOverlays and !hasTwoOverlays on
|
|
* the fly.
|
|
*/
|
|
|
|
if(pSiS->VGAEngine == SIS_300_VGA) {
|
|
pPriv->linebufmask = 0x11;
|
|
pPriv->linebufMergeLimit = 384;
|
|
} else {
|
|
pPriv->linebufmask = 0xb1;
|
|
pPriv->linebufMergeLimit = 384; /* should be 480 */
|
|
if(pPriv->is661741760) {
|
|
pPriv->linebufMergeLimit = 576; /* should be 768 */
|
|
} else if(pPriv->is340) {
|
|
pPriv->linebufMergeLimit = 1280; /* should be 1280 */
|
|
} else if(pPriv->is761) {
|
|
pPriv->linebufMergeLimit = 1280; /* should be 1536 */
|
|
} else if(pPriv->isXGI) {
|
|
pPriv->linebufMergeLimit = 1280; /* FIXME */
|
|
} else if(!(pPriv->hasTwoOverlays)) {
|
|
pPriv->linebufMergeLimit = 720; /* should be 960 */
|
|
}
|
|
/* No special treatment for 760/761 required */
|
|
}
|
|
|
|
set_maxencoding(pSiS, pPriv);
|
|
|
|
/* Reset the properties to their defaults */
|
|
SISSetPortDefaults(pScrn, pPriv);
|
|
|
|
/* Set SR(06, 32) registers according to DISPMODE */
|
|
set_disptype_regs(pScrn, pPriv);
|
|
|
|
SISResetVideo(pScrn);
|
|
pSiS->ResetXv = SISResetVideo;
|
|
pSiS->ResetXvDisplay = SISResetXvDisplay;
|
|
if(pSiS->VGAEngine == SIS_315_VGA) {
|
|
pSiS->ResetXvGamma = SISResetXvGamma;
|
|
}
|
|
|
|
return adapt;
|
|
}
|
|
|
|
#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,3,99,3,0)
|
|
static Bool
|
|
RegionsEqual(RegionPtr A, RegionPtr B)
|
|
{
|
|
int *dataA, *dataB;
|
|
int num;
|
|
|
|
num = REGION_NUM_RECTS(A);
|
|
if(num != REGION_NUM_RECTS(B))
|
|
return FALSE;
|
|
|
|
if((A->extents.x1 != B->extents.x1) ||
|
|
(A->extents.x2 != B->extents.x2) ||
|
|
(A->extents.y1 != B->extents.y1) ||
|
|
(A->extents.y2 != B->extents.y2))
|
|
return FALSE;
|
|
|
|
dataA = (int*)REGION_RECTS(A);
|
|
dataB = (int*)REGION_RECTS(B);
|
|
|
|
while(num--) {
|
|
if((dataA[0] != dataB[0]) || (dataA[1] != dataB[1]))
|
|
return FALSE;
|
|
dataA += 2;
|
|
dataB += 2;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
#endif
|
|
|
|
/*********************************
|
|
* SetPortAttribute() *
|
|
*********************************/
|
|
|
|
void
|
|
SISUpdateVideoParms(SISPtr pSiS, SISPortPrivPtr pPriv)
|
|
{
|
|
set_hastwooverlays(pSiS, pPriv);
|
|
set_allowswitchcrt(pSiS, pPriv);
|
|
set_dispmode(pSiS->pScrn, pPriv);
|
|
set_maxencoding(pSiS, pPriv);
|
|
}
|
|
|
|
static int
|
|
SISSetPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
|
|
INT32 value, pointer data)
|
|
{
|
|
SISPortPrivPtr pPriv = (SISPortPrivPtr)data;
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
#ifdef SISDUALHEAD
|
|
SISEntPtr pSiSEnt = pSiS->entityPrivate;;
|
|
#endif
|
|
|
|
if(attribute == pSiS->xvBrightness) {
|
|
if((value < -128) || (value > 127))
|
|
return BadValue;
|
|
pPriv->brightness = value;
|
|
} else if(attribute == pSiS->xvContrast) {
|
|
if((value < 0) || (value > 7))
|
|
return BadValue;
|
|
pPriv->contrast = value;
|
|
} else if(attribute == pSiS->xvColorKey) {
|
|
pPriv->colorKey = pSiS->colorKey = value;
|
|
REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
|
|
} else if(attribute == pSiS->xvAutopaintColorKey) {
|
|
if((value < 0) || (value > 1))
|
|
return BadValue;
|
|
pPriv->autopaintColorKey = value;
|
|
} else if(attribute == pSiS->xvSetDefaults) {
|
|
SISSetPortDefaults(pScrn, pPriv);
|
|
} else if(attribute == pSiS->xvDisableGfx) {
|
|
if((value < 0) || (value > 1))
|
|
return BadValue;
|
|
pPriv->disablegfx = value;
|
|
} else if(attribute == pSiS->xvDisableGfxLR) {
|
|
if((value < 0) || (value > 1))
|
|
return BadValue;
|
|
pPriv->disablegfxlr = value;
|
|
} else if(attribute == pSiS->xvTVXPosition) {
|
|
if((value < -32) || (value > 32))
|
|
return BadValue;
|
|
pPriv->tvxpos = value;
|
|
if(pSiS->xv_sisdirectunlocked) {
|
|
SiS_SetTVxposoffset(pScrn, pPriv->tvxpos);
|
|
pPriv->updatetvxpos = FALSE;
|
|
} else {
|
|
pSiS->tvxpos = pPriv->tvxpos;
|
|
#ifdef SISDUALHEAD
|
|
if(pPriv->dualHeadMode) pSiSEnt->tvxpos = pPriv->tvxpos;
|
|
#endif
|
|
pPriv->updatetvxpos = TRUE;
|
|
}
|
|
} else if(attribute == pSiS->xvTVYPosition) {
|
|
if((value < -32) || (value > 32)) return BadValue;
|
|
pPriv->tvypos = value;
|
|
if(pSiS->xv_sisdirectunlocked) {
|
|
SiS_SetTVyposoffset(pScrn, pPriv->tvypos);
|
|
pPriv->updatetvypos = FALSE;
|
|
} else {
|
|
pSiS->tvypos = pPriv->tvypos;
|
|
#ifdef SISDUALHEAD
|
|
if(pPriv->dualHeadMode) pSiSEnt->tvypos = pPriv->tvypos;
|
|
#endif
|
|
pPriv->updatetvypos = TRUE;
|
|
}
|
|
} else if(attribute == pSiS->xvDisableColorkey) {
|
|
if((value < 0) || (value > 1)) return BadValue;
|
|
pSiS->disablecolorkeycurrent = value;
|
|
} else if(attribute == pSiS->xvUseChromakey) {
|
|
if((value < 0) || (value > 1)) return BadValue;
|
|
pPriv->usechromakey = value;
|
|
} else if(attribute == pSiS->xvInsideChromakey) {
|
|
if((value < 0) || (value > 1)) return BadValue;
|
|
pPriv->insidechromakey = value;
|
|
} else if(attribute == pSiS->xvYUVChromakey) {
|
|
if((value < 0) || (value > 1)) return BadValue;
|
|
pPriv->yuvchromakey = value;
|
|
} else if(attribute == pSiS->xvChromaMin) {
|
|
pPriv->chromamin = value;
|
|
} else if(attribute == pSiS->xvChromaMax) {
|
|
pPriv->chromamax = value;
|
|
#ifdef SISDEINT
|
|
} else if(attribute == pSiS->xvdeintmeth) {
|
|
if(value < 0) value = 0;
|
|
if(value > 4) value = 4;
|
|
pPriv->deinterlacemethod = value;
|
|
#endif
|
|
#ifdef SIS_CP
|
|
SIS_CP_VIDEO_SETATTRIBUTE
|
|
#endif
|
|
} else if(attribute == pSiS->xvHue) {
|
|
if(pSiS->VGAEngine == SIS_315_VGA) {
|
|
if((value < -8) || (value > 7)) return BadValue;
|
|
pPriv->hue = value;
|
|
} else return BadMatch;
|
|
} else if(attribute == pSiS->xvSaturation) {
|
|
if(pSiS->VGAEngine == SIS_315_VGA) {
|
|
if((value < -7) || (value > 7)) return BadValue;
|
|
pPriv->saturation = value;
|
|
} else return BadMatch;
|
|
} else if(attribute == pSiS->xvGammaRed) {
|
|
if(pSiS->VGAEngine == SIS_315_VGA) {
|
|
if((value < 100) || (value > 10000)) return BadValue;
|
|
pSiS->XvGammaRed = value;
|
|
SiSUpdateXvGamma(pSiS, pPriv);
|
|
} else return BadMatch;
|
|
} else if(attribute == pSiS->xvGammaGreen) {
|
|
if(pSiS->VGAEngine == SIS_315_VGA) {
|
|
if((value < 100) || (value > 10000)) return BadValue;
|
|
pSiS->XvGammaGreen = value;
|
|
SiSUpdateXvGamma(pSiS, pPriv);
|
|
} else return BadMatch;
|
|
} else if(attribute == pSiS->xvGammaBlue) {
|
|
if(pSiS->VGAEngine == SIS_315_VGA) {
|
|
if((value < 100) || (value > 10000)) return BadValue;
|
|
pSiS->XvGammaBlue = value;
|
|
SiSUpdateXvGamma(pSiS, pPriv);
|
|
} else return BadMatch;
|
|
} else if(attribute == pSiS->xvSwitchCRT) {
|
|
if(pSiS->VGAEngine == SIS_315_VGA) {
|
|
if(pPriv->AllowSwitchCRT) {
|
|
if((value < 0) || (value > 1))
|
|
return BadValue;
|
|
pPriv->crtnum = value;
|
|
#ifdef SISDUALHEAD
|
|
if(pPriv->dualHeadMode) pSiSEnt->curxvcrtnum = value;
|
|
#endif
|
|
}
|
|
} else return BadMatch;
|
|
} else {
|
|
#ifdef XV_SD_DEPRECATED
|
|
return(SISSetPortUtilAttribute(pScrn, attribute, value, pPriv));
|
|
#else
|
|
return BadMatch;
|
|
#endif
|
|
}
|
|
return Success;
|
|
}
|
|
|
|
/*********************************
|
|
* GetPortAttribute() *
|
|
*********************************/
|
|
|
|
static int
|
|
SISGetPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
|
|
INT32 *value, pointer data)
|
|
{
|
|
SISPortPrivPtr pPriv = (SISPortPrivPtr)data;
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
#ifdef SISDUALHEAD
|
|
SISEntPtr pSiSEnt = pSiS->entityPrivate;;
|
|
#endif
|
|
|
|
if(attribute == pSiS->xvBrightness) {
|
|
*value = pPriv->brightness;
|
|
} else if(attribute == pSiS->xvContrast) {
|
|
*value = pPriv->contrast;
|
|
} else if(attribute == pSiS->xvColorKey) {
|
|
*value = pPriv->colorKey;
|
|
} else if(attribute == pSiS->xvAutopaintColorKey) {
|
|
*value = (pPriv->autopaintColorKey) ? 1 : 0;
|
|
} else if(attribute == pSiS->xvDisableGfx) {
|
|
*value = (pPriv->disablegfx) ? 1 : 0;
|
|
} else if(attribute == pSiS->xvDisableGfxLR) {
|
|
*value = (pPriv->disablegfxlr) ? 1 : 0;
|
|
} else if(attribute == pSiS->xvTVXPosition) {
|
|
*value = SiS_GetTVxposoffset(pScrn);
|
|
} else if(attribute == pSiS->xvTVYPosition) {
|
|
*value = SiS_GetTVyposoffset(pScrn);
|
|
} else if(attribute == pSiS->xvDisableColorkey) {
|
|
*value = (pSiS->disablecolorkeycurrent) ? 1 : 0;
|
|
} else if(attribute == pSiS->xvUseChromakey) {
|
|
*value = (pPriv->usechromakey) ? 1 : 0;
|
|
} else if(attribute == pSiS->xvInsideChromakey) {
|
|
*value = (pPriv->insidechromakey) ? 1 : 0;
|
|
} else if(attribute == pSiS->xvYUVChromakey) {
|
|
*value = (pPriv->yuvchromakey) ? 1 : 0;
|
|
} else if(attribute == pSiS->xvChromaMin) {
|
|
*value = pPriv->chromamin;
|
|
} else if(attribute == pSiS->xvChromaMax) {
|
|
*value = pPriv->chromamax;
|
|
#ifdef SISDEINT
|
|
} else if(attribute == pSiS->xvdeintmeth) {
|
|
*value = pPriv->deinterlacemethod;
|
|
#endif
|
|
#ifdef SIS_CP
|
|
SIS_CP_VIDEO_GETATTRIBUTE
|
|
#endif
|
|
} else if(attribute == pSiS->xvHue) {
|
|
if(pSiS->VGAEngine == SIS_315_VGA) {
|
|
*value = pPriv->hue;
|
|
} else return BadMatch;
|
|
} else if(attribute == pSiS->xvSaturation) {
|
|
if(pSiS->VGAEngine == SIS_315_VGA) {
|
|
*value = pPriv->saturation;
|
|
} else return BadMatch;
|
|
} else if(attribute == pSiS->xvGammaRed) {
|
|
if(pSiS->VGAEngine == SIS_315_VGA) {
|
|
*value = pSiS->XvGammaRed;
|
|
} else return BadMatch;
|
|
} else if(attribute == pSiS->xvGammaGreen) {
|
|
if(pSiS->VGAEngine == SIS_315_VGA) {
|
|
*value = pSiS->XvGammaGreen;
|
|
} else return BadMatch;
|
|
} else if(attribute == pSiS->xvGammaBlue) {
|
|
if(pSiS->VGAEngine == SIS_315_VGA) {
|
|
*value = pSiS->XvGammaBlue;
|
|
} else return BadMatch;
|
|
} else if(attribute == pSiS->xvSwitchCRT) {
|
|
if(pSiS->VGAEngine == SIS_315_VGA) {
|
|
#ifdef SISDUALHEAD
|
|
if(pPriv->dualHeadMode)
|
|
*value = pSiSEnt->curxvcrtnum;
|
|
else
|
|
#endif
|
|
*value = pPriv->crtnum;
|
|
} else return BadMatch;
|
|
} else {
|
|
#ifdef XV_SD_DEPRECATED
|
|
return(SISGetPortUtilAttribute(pScrn, attribute, value, pPriv));
|
|
#else
|
|
return BadMatch;
|
|
#endif
|
|
}
|
|
return Success;
|
|
}
|
|
|
|
/*********************************
|
|
* QueryBestSize() *
|
|
*********************************/
|
|
|
|
static void
|
|
SISQueryBestSize(
|
|
ScrnInfoPtr pScrn,
|
|
Bool motion,
|
|
short vid_w, short vid_h,
|
|
short drw_w, short drw_h,
|
|
unsigned int *p_w, unsigned int *p_h,
|
|
pointer data
|
|
){
|
|
*p_w = drw_w;
|
|
*p_h = drw_h;
|
|
}
|
|
|
|
/*********************************
|
|
* Calc scaling factor *
|
|
*********************************/
|
|
|
|
static void
|
|
calc_scale_factor(SISOverlayPtr pOverlay, ScrnInfoPtr pScrn,
|
|
SISPortPrivPtr pPriv, int index, int iscrt2)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
CARD32 I=0,mult=0;
|
|
int flag=0, flag2=0;
|
|
|
|
int dstW = pOverlay->dstBox.x2 - pOverlay->dstBox.x1;
|
|
int dstH = pOverlay->dstBox.y2 - pOverlay->dstBox.y1;
|
|
int srcW = pOverlay->srcW;
|
|
int srcH = pOverlay->srcH;
|
|
CARD16 LCDheight = pSiS->LCDheight;
|
|
int srcPitch = pOverlay->origPitch;
|
|
int origdstH = dstH;
|
|
int modeflags = pOverlay->currentmode->Flags;
|
|
|
|
/* Stretch image due to panel link scaling */
|
|
if(pSiS->VBFlags & (CRT2_LCD | CRT1_LCDA)) {
|
|
if(pPriv->bridgeIsSlave) {
|
|
if(pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH)) {
|
|
if(pSiS->MiscFlags & MISC_PANELLINKSCALER) {
|
|
dstH = (dstH * LCDheight) / pOverlay->SCREENheight;
|
|
}
|
|
}
|
|
} else if((iscrt2 && (pSiS->VBFlags & CRT2_LCD)) ||
|
|
(!iscrt2 && (pSiS->VBFlags & CRT1_LCDA))) {
|
|
if((pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH)) || (pSiS->VBFlags & CRT1_LCDA)) {
|
|
if(pSiS->MiscFlags & MISC_PANELLINKSCALER) {
|
|
dstH = (dstH * LCDheight) / pOverlay->SCREENheight;
|
|
if(pPriv->displayMode == DISPMODE_MIRROR) flag = 1;
|
|
}
|
|
}
|
|
}
|
|
if((pPriv->bridgeIsSlave || iscrt2) &&
|
|
(pSiS->MiscFlags & MISC_STNMODE)) {
|
|
flag2 = 1;
|
|
}
|
|
}
|
|
|
|
/* For double scan modes, we need to double the height
|
|
* On 315 and 550 (?), we need to double the width as well.
|
|
* Interlace mode vice versa.
|
|
*/
|
|
if((modeflags & V_DBLSCAN) && !flag2) {
|
|
dstH = origdstH << 1;
|
|
flag = 0;
|
|
if((pSiS->ChipType >= SIS_315H) &&
|
|
(pSiS->ChipType <= SIS_550)) {
|
|
dstW <<= 1;
|
|
}
|
|
} else if(modeflags & V_INTERLACE) {
|
|
dstH = origdstH >> 1;
|
|
flag = 0;
|
|
}
|
|
|
|
pOverlay->tap_scale = 1.0;
|
|
|
|
if(dstW < OVERLAY_MIN_WIDTH) dstW = OVERLAY_MIN_WIDTH;
|
|
|
|
if(dstW == srcW) {
|
|
|
|
pOverlay->HUSF = 0x00;
|
|
pOverlay->IntBit = 0x05;
|
|
pOverlay->wHPre = 0;
|
|
|
|
} else if(dstW > srcW) {
|
|
|
|
pOverlay->IntBit = 0x04;
|
|
pOverlay->wHPre = 0;
|
|
|
|
if(pPriv->havetapscaler) {
|
|
if((dstW > 2) && (srcW > 2)) {
|
|
pOverlay->HUSF = (((srcW - 2) << 16) + dstW - 3) / (dstW - 2);
|
|
} else {
|
|
pOverlay->HUSF = ((srcW << 16) + dstW - 1) / dstW;
|
|
}
|
|
} else {
|
|
dstW += 2;
|
|
pOverlay->HUSF = (srcW << 16) / dstW;
|
|
}
|
|
|
|
} else {
|
|
|
|
int tmpW = dstW;
|
|
|
|
/* It seems, the hardware can't scale below factor .125 (=1/8) if the
|
|
pitch isn't a multiple of 256.
|
|
TODO: Test this on the 315 series!
|
|
*/
|
|
if((srcPitch % 256) || (srcPitch < 256)) {
|
|
if(((dstW * 1000) / srcW) < 125) dstW = tmpW = ((srcW * 125) / 1000) + 1;
|
|
}
|
|
|
|
I = 0;
|
|
pOverlay->IntBit = 0x01;
|
|
while(srcW >= tmpW) {
|
|
tmpW <<= 1;
|
|
I++;
|
|
}
|
|
pOverlay->wHPre = (CARD8)(I - 1);
|
|
dstW <<= (I - 1);
|
|
|
|
pOverlay->tap_scale = (float)srcW / (float)dstW;
|
|
if(pOverlay->tap_scale < 1.0) pOverlay->tap_scale = 1.0;
|
|
|
|
if((srcW % dstW))
|
|
pOverlay->HUSF = ((srcW - dstW) << 16) / dstW;
|
|
else
|
|
pOverlay->HUSF = 0;
|
|
}
|
|
|
|
if(dstH < OVERLAY_MIN_HEIGHT) dstH = OVERLAY_MIN_HEIGHT;
|
|
|
|
if(dstH == srcH) {
|
|
|
|
pOverlay->VUSF = 0x00;
|
|
pOverlay->IntBit |= 0x0A;
|
|
|
|
} else if(dstH > srcH) {
|
|
|
|
dstH += 2;
|
|
pOverlay->IntBit |= 0x08;
|
|
|
|
if(pPriv->havetapscaler) {
|
|
if((dstH > 2) && (srcH > 2)) {
|
|
pOverlay->VUSF = (((srcH - 2) << 16) - 32768 + dstH - 3) / (dstH - 2);
|
|
} else {
|
|
pOverlay->VUSF = ((srcH << 16) + dstH - 1) / dstH;
|
|
}
|
|
} else {
|
|
pOverlay->VUSF = (srcH << 16) / dstH;
|
|
}
|
|
|
|
} else {
|
|
|
|
I = srcH / dstH;
|
|
pOverlay->IntBit |= 0x02;
|
|
|
|
if(I < 2) {
|
|
pOverlay->VUSF = ((srcH - dstH) << 16) / dstH;
|
|
/* Needed for LCD-scaling modes */
|
|
if((flag) && (mult = (srcH / origdstH)) >= 2) {
|
|
pOverlay->pitch /= mult;
|
|
}
|
|
} else {
|
|
#if 0
|
|
if(((pOverlay->bobEnable & 0x08) == 0x00) &&
|
|
(((srcPitch * I) >> 2) > 0xFFF)){
|
|
pOverlay->bobEnable |= 0x08;
|
|
srcPitch >>= 1;
|
|
}
|
|
#endif
|
|
if(((srcPitch * I) >> 2) > 0xFFF) {
|
|
I = (0xFFF * 2 / srcPitch);
|
|
pOverlay->VUSF = 0xFFFF;
|
|
} else {
|
|
dstH = I * dstH;
|
|
if(srcH % dstH)
|
|
pOverlay->VUSF = ((srcH - dstH) << 16) / dstH;
|
|
else
|
|
pOverlay->VUSF = 0;
|
|
}
|
|
/* set video frame buffer offset */
|
|
pOverlay->pitch = (CARD16)(srcPitch * I);
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef SISMERGED
|
|
static void
|
|
calc_scale_factor_2(SISOverlayPtr pOverlay, ScrnInfoPtr pScrn,
|
|
SISPortPrivPtr pPriv, int index, int iscrt2)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
CARD32 I=0,mult=0;
|
|
int flag=0, flag2=0;
|
|
|
|
int dstW = pOverlay->dstBox2.x2 - pOverlay->dstBox2.x1;
|
|
int dstH = pOverlay->dstBox2.y2 - pOverlay->dstBox2.y1;
|
|
int srcW = pOverlay->srcW2;
|
|
int srcH = pOverlay->srcH2;
|
|
CARD16 LCDheight = pSiS->LCDheight;
|
|
int srcPitch = pOverlay->origPitch;
|
|
int origdstH = dstH;
|
|
int modeflags = pOverlay->currentmode2->Flags;
|
|
|
|
/* Stretch image due to panel link scaling */
|
|
if(pSiS->VBFlags & CRT2_LCD) {
|
|
if(pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH)) {
|
|
if(pSiS->MiscFlags & MISC_PANELLINKSCALER) {
|
|
dstH = (dstH * LCDheight) / pOverlay->SCREENheight2;
|
|
flag = 1;
|
|
}
|
|
if(pSiS->MiscFlags & MISC_STNMODE) flag2 = 1;
|
|
}
|
|
}
|
|
/* For double scan modes, we need to double the height
|
|
* On 315 and 550 (?), we need to double the width as well.
|
|
* Interlace mode vice versa.
|
|
*/
|
|
if((modeflags & V_DBLSCAN) && !flag2) {
|
|
dstH = origdstH << 1;
|
|
flag = 0;
|
|
if((pSiS->ChipType >= SIS_315H) &&
|
|
(pSiS->ChipType <= SIS_550)) {
|
|
dstW <<= 1;
|
|
}
|
|
}
|
|
if(modeflags & V_INTERLACE) {
|
|
dstH = origdstH >> 1;
|
|
flag = 0;
|
|
}
|
|
|
|
pOverlay->tap_scale2 = 1.0;
|
|
|
|
if(dstW < OVERLAY_MIN_WIDTH) dstW = OVERLAY_MIN_WIDTH;
|
|
|
|
if(dstW == srcW) {
|
|
|
|
pOverlay->HUSF2 = 0x00;
|
|
pOverlay->IntBit2 = 0x05;
|
|
pOverlay->wHPre2 = 0;
|
|
|
|
} else if(dstW > srcW) {
|
|
|
|
pOverlay->IntBit2 = 0x04;
|
|
pOverlay->wHPre2 = 0;
|
|
|
|
if(pPriv->havetapscaler) {
|
|
if((dstW > 2) && (srcW > 2)) {
|
|
pOverlay->HUSF2 = (((srcW - 2) << 16) + dstW - 3) / (dstW - 2);
|
|
} else {
|
|
pOverlay->HUSF2 = ((srcW << 16) + dstW - 1) / dstW;
|
|
}
|
|
} else {
|
|
dstW += 2;
|
|
pOverlay->HUSF2 = (srcW << 16) / dstW;
|
|
}
|
|
|
|
} else {
|
|
|
|
int tmpW = dstW;
|
|
|
|
/* It seems, the hardware can't scale below factor .125 (=1/8) if the
|
|
pitch isn't a multiple of 256.
|
|
TODO: Test this on the 315 series!
|
|
*/
|
|
if((srcPitch % 256) || (srcPitch < 256)) {
|
|
if(((dstW * 1000) / srcW) < 125) dstW = tmpW = ((srcW * 125) / 1000) + 1;
|
|
}
|
|
|
|
I = 0;
|
|
pOverlay->IntBit2 = 0x01;
|
|
while(srcW >= tmpW) {
|
|
tmpW <<= 1;
|
|
I++;
|
|
}
|
|
pOverlay->wHPre2 = (CARD8)(I - 1);
|
|
dstW <<= (I - 1);
|
|
|
|
pOverlay->tap_scale2 = (float)srcW / (float)dstW;
|
|
if(pOverlay->tap_scale2 < 1.0) pOverlay->tap_scale2 = 1.0;
|
|
|
|
if((srcW % dstW))
|
|
pOverlay->HUSF2 = ((srcW - dstW) << 16) / dstW;
|
|
else
|
|
pOverlay->HUSF2 = 0x00;
|
|
}
|
|
|
|
if(dstH < OVERLAY_MIN_HEIGHT) dstH = OVERLAY_MIN_HEIGHT;
|
|
|
|
if(dstH == srcH) {
|
|
|
|
pOverlay->VUSF2 = 0x00;
|
|
pOverlay->IntBit2 |= 0x0A;
|
|
|
|
} else if(dstH > srcH) {
|
|
|
|
dstH += 2;
|
|
pOverlay->IntBit2 |= 0x08;
|
|
|
|
if(pPriv->havetapscaler) {
|
|
if((dstH > 2) && (srcH > 2)) {
|
|
pOverlay->VUSF2 = (((srcH - 2) << 16) - 32768 + dstH - 3) / (dstH - 2);
|
|
} else {
|
|
pOverlay->VUSF2 = ((srcH << 16) + dstH - 1) / dstH;
|
|
}
|
|
} else {
|
|
pOverlay->VUSF2 = (srcH << 16) / dstH;
|
|
}
|
|
|
|
} else {
|
|
|
|
I = srcH / dstH;
|
|
pOverlay->IntBit2 |= 0x02;
|
|
|
|
if(I < 2) {
|
|
pOverlay->VUSF2 = ((srcH - dstH) << 16) / dstH;
|
|
/* Needed for LCD-scaling modes */
|
|
if(flag && ((mult = (srcH / origdstH)) >= 2)) {
|
|
pOverlay->pitch2 /= mult;
|
|
}
|
|
} else {
|
|
#if 0
|
|
if(((pOverlay->bobEnable & 0x08) == 0x00) &&
|
|
(((srcPitch * I)>>2) > 0xFFF)){
|
|
pOverlay->bobEnable |= 0x08;
|
|
srcPitch >>= 1;
|
|
}
|
|
#endif
|
|
if(((srcPitch * I) >> 2) > 0xFFF) {
|
|
I = (0xFFF * 2 / srcPitch);
|
|
pOverlay->VUSF2 = 0xFFFF;
|
|
} else {
|
|
dstH = I * dstH;
|
|
if(srcH % dstH)
|
|
pOverlay->VUSF2 = ((srcH - dstH) << 16) / dstH;
|
|
else
|
|
pOverlay->VUSF2 = 0x00;
|
|
}
|
|
/* set video frame buffer offset */
|
|
pOverlay->pitch2 = (CARD16)(srcPitch * I);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*********************************
|
|
* Handle 4-tap scaler (340) *
|
|
*********************************/
|
|
|
|
static float
|
|
tap_dda_func(float x)
|
|
{
|
|
double pi = 3.14159265358979;
|
|
float r = 0.5, y;
|
|
|
|
if(x == 0.0) {
|
|
y = 1.0;
|
|
} else if(x == -1.0 || x == 1.0) {
|
|
y = 0.0;
|
|
/* case ((x == -1.0 / (r * 2.0)) || (x == 1.0 / (r * 2.0))): */
|
|
/* y = (float)(r / 2.0 * sin(pi / (2.0 * r))); = 0.013700916287197; */
|
|
} else {
|
|
y = sin(pi * x) / (pi * x) * cos(r * pi * x) / (1 - x * x);
|
|
/* y = sin(pi * x) / (pi * x) * cos(r * pi * x) / (1 - 4 * r * r * x * x); */
|
|
}
|
|
|
|
return y;
|
|
}
|
|
|
|
static void
|
|
set_dda_regs(SISPtr pSiS, float scale)
|
|
{
|
|
float W[4], WS, myadd;
|
|
int *temp[4], *wm1, *wm2, *wm3, *wm4;
|
|
int i, j, w, tidx, weightmatrix[16][4];
|
|
|
|
for(i = 0; i < 16; i++) {
|
|
|
|
myadd = ((float)i) / 16.0;
|
|
WS = W[0] = tap_dda_func((myadd + 1.0) / scale);
|
|
W[1] = tap_dda_func(myadd / scale);
|
|
WS += W[1];
|
|
W[2] = tap_dda_func((myadd - 1.0) / scale);
|
|
WS += W[2];
|
|
W[3] = tap_dda_func((myadd - 2.0) / scale);
|
|
WS += W[3];
|
|
|
|
w = 0;
|
|
for(j = 0; j < 4; j++) {
|
|
weightmatrix[i][j] = (int)(((float)((W[j] * 16.0 / WS) + 0.5)));
|
|
w += weightmatrix[i][j];
|
|
}
|
|
|
|
if(w == 12) {
|
|
|
|
weightmatrix[i][0]++;
|
|
weightmatrix[i][1]++;
|
|
weightmatrix[i][2]++;
|
|
weightmatrix[i][3]++;
|
|
|
|
} else if(w == 20) {
|
|
|
|
weightmatrix[i][0]--;
|
|
weightmatrix[i][1]--;
|
|
weightmatrix[i][2]--;
|
|
weightmatrix[i][3]--;
|
|
|
|
} else if(w != 16) {
|
|
|
|
tidx = (weightmatrix[i][0] > weightmatrix[i][1]) ? 0 : 1;
|
|
temp[0] = &weightmatrix[i][tidx];
|
|
temp[1] = &weightmatrix[i][tidx ^ 1];
|
|
|
|
tidx = (weightmatrix[i][2] > weightmatrix[i][3]) ? 2 : 3;
|
|
temp[2] = &weightmatrix[i][tidx];
|
|
temp[3] = &weightmatrix[i][tidx ^ 1];
|
|
|
|
tidx = (*(temp[0]) > *(temp[2])) ? 0 : 2;
|
|
wm1 = temp[tidx];
|
|
wm2 = temp[tidx ^ 2];
|
|
|
|
tidx = (*(temp[1]) > *(temp[3])) ? 1 : 3;
|
|
wm3 = temp[tidx];
|
|
wm4 = temp[tidx ^ 2];
|
|
|
|
switch(w) {
|
|
case 13:
|
|
(*wm1)++;
|
|
(*wm4)++;
|
|
if(*wm2 > *wm3) (*wm2)++;
|
|
else (*wm3)++;
|
|
break;
|
|
case 14:
|
|
(*wm1)++;
|
|
(*wm4)++;
|
|
break;
|
|
case 15:
|
|
(*wm1)++;
|
|
break;
|
|
case 17:
|
|
(*wm4)--;
|
|
break;
|
|
case 18:
|
|
(*wm1)--;
|
|
(*wm4)--;
|
|
break;
|
|
case 19:
|
|
(*wm1)--;
|
|
(*wm4)--;
|
|
if(*wm2 > *wm3) (*wm3)--;
|
|
else (*wm2)--;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Set 4-tap scaler video regs 0x75-0xb4 */
|
|
w = 0x75;
|
|
for(i = 0; i < 16; i++) {
|
|
for(j = 0; j < 4; j++, w++) {
|
|
setvideoregmask(pSiS, w, weightmatrix[i][j], 0x3f);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*********************************
|
|
* Calc line buffer size *
|
|
*********************************/
|
|
|
|
static CARD16
|
|
calc_line_buf_size(CARD32 srcW, CARD8 wHPre, CARD8 planar, SISPortPrivPtr pPriv)
|
|
{
|
|
CARD32 I, mask = 0xffffffff, shift = pPriv->is761 ? 1 : 0;
|
|
|
|
if(planar) {
|
|
|
|
switch(wHPre & 0x07) {
|
|
case 3:
|
|
shift += 8;
|
|
mask <<= shift;
|
|
I = srcW >> shift;
|
|
if((mask & srcW) != srcW) I++;
|
|
I <<= 5;
|
|
break;
|
|
case 4:
|
|
shift += 9;
|
|
mask <<= shift;
|
|
I = srcW >> shift;
|
|
if((mask & srcW) != srcW) I++;
|
|
I <<= 6;
|
|
break;
|
|
case 5:
|
|
shift += 10;
|
|
mask <<= shift;
|
|
I = srcW >> shift;
|
|
if((mask & srcW) != srcW) I++;
|
|
I <<= 7;
|
|
break;
|
|
case 6:
|
|
if(pPriv->is340 || pPriv->isXGI || pPriv->is761) {
|
|
shift += 11;
|
|
mask <<= shift;
|
|
I = srcW >> shift;
|
|
if((mask & srcW) != srcW) I++;
|
|
I <<= 8;
|
|
break;
|
|
} else {
|
|
return((CARD16)(255));
|
|
}
|
|
default:
|
|
shift += 7;
|
|
mask <<= shift;
|
|
I = srcW >> shift;
|
|
if((mask & srcW) != srcW) I++;
|
|
I <<= 4;
|
|
break;
|
|
}
|
|
|
|
} else { /* packed */
|
|
|
|
shift += 3;
|
|
mask <<= shift;
|
|
I = srcW >> shift;
|
|
if((mask & srcW) != srcW) I++;
|
|
|
|
}
|
|
|
|
if(I <= 3) I = 4;
|
|
|
|
return((CARD16)(I - 1));
|
|
}
|
|
|
|
static __inline void
|
|
calc_line_buf_size_1(SISOverlayPtr pOverlay, SISPortPrivPtr pPriv)
|
|
{
|
|
pOverlay->lineBufSize =
|
|
calc_line_buf_size(pOverlay->srcW, pOverlay->wHPre, pOverlay->planar, pPriv);
|
|
}
|
|
|
|
#ifdef SISMERGED
|
|
static __inline void
|
|
calc_line_buf_size_2(SISOverlayPtr pOverlay, SISPortPrivPtr pPriv)
|
|
{
|
|
pOverlay->lineBufSize2 =
|
|
calc_line_buf_size(pOverlay->srcW2, pOverlay->wHPre2, pOverlay->planar, pPriv);
|
|
}
|
|
|
|
/**********************************
|
|
*En/Disable merging of linebuffer*
|
|
**********************************/
|
|
|
|
static void
|
|
merge_line_buf_mfb(SISPtr pSiS, SISPortPrivPtr pPriv, Bool enable1, Bool enable2,
|
|
short width1, short width2, short limit)
|
|
{
|
|
UChar misc1, misc2, mask = pPriv->linebufmask;
|
|
|
|
if(pPriv->hasTwoOverlays) { /* This means we are in MIRROR mode */
|
|
|
|
misc2 = 0x00;
|
|
if(enable1) misc1 = 0x04;
|
|
else misc1 = 0x00;
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc2, misc2, mask);
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc1, misc1, 0x04);
|
|
|
|
misc2 = 0x01;
|
|
if(enable2) misc1 = 0x04;
|
|
else misc1 = 0x00;
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc2, misc2, mask);
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc1, misc1, 0x04);
|
|
|
|
} else { /* This means we are either in SINGLE1 or SINGLE2 mode */
|
|
|
|
misc2 = 0x00;
|
|
if(enable1 || enable2) {
|
|
if(pSiS->MiscFlags & MISC_SIS760ONEOVERLAY) {
|
|
if((width1 > (limit * 2)) || (width2 > (limit * 2))) {
|
|
misc2 = 0x20;
|
|
} else {
|
|
misc2 = 0x10;
|
|
}
|
|
misc1 = 0x00;
|
|
} else {
|
|
misc1 = 0x04;
|
|
}
|
|
} else {
|
|
misc1 = 0x00;
|
|
}
|
|
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc2, misc2, mask);
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc1, misc1, 0x04);
|
|
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* About linebuffer merging:
|
|
*
|
|
* For example the 651:
|
|
* Each overlay has 4 line buffers, 384 bytes each (<-- Is that really correct? 1920 / 384 = 5 !!!)
|
|
* If the source width is greater than 384, line buffers must be merged.
|
|
* Dual merge: Only O1 usable (uses overlay 2's linebuffer), maximum width 384*2
|
|
* Individual merge: Both overlays available, maximum width 384*2
|
|
* All merge: Only overlay 1 available, maximum width = 384*4 (<--- should be 1920, is 1536...)
|
|
*
|
|
*
|
|
* Normally: Dual merge: Individual merge
|
|
* Overlay 1 Overlay 2 Overlay 1 only! Both overlays
|
|
* ___1___ ___5___ ___1___ ___2___ -\ O1 ___1___ ___2___
|
|
* ___2___ ___6___ ___3___ ___4___ \_ O 1 O1 ___3___ ___4___
|
|
* ___3___ ___7___ ___5___ ___6___ / O2 ___5___ ___6___
|
|
* ___4___ ___8___ ___7___ ___8___ -/ O2 ___7___ ___8___
|
|
*
|
|
*
|
|
* All merge: ___1___ ___2___ ___3___ ___4___
|
|
* (Overlay 1 only!) ___5___ ___6___ ___7___ ___8___
|
|
*
|
|
* Individual merge is supported on all chipsets.
|
|
* Dual merge is only supported on the 300 series and M650/651 and later.
|
|
* All merge is only supported on the M650/651 and later.
|
|
* Single-Overlay-chipsets only support Individual merge.
|
|
*
|
|
*/
|
|
|
|
static void
|
|
merge_line_buf(SISPtr pSiS, SISPortPrivPtr pPriv, Bool enable, short width, short limit)
|
|
{
|
|
UChar misc1, misc2, mask = pPriv->linebufmask;
|
|
|
|
if(enable) { /* ----- enable linebuffer merge */
|
|
|
|
switch(pPriv->displayMode){
|
|
case DISPMODE_SINGLE1:
|
|
if(pSiS->VGAEngine == SIS_300_VGA) {
|
|
if(pPriv->dualHeadMode) {
|
|
misc2 = 0x00;
|
|
misc1 = 0x04;
|
|
} else {
|
|
misc2 = 0x10;
|
|
misc1 = 0x00;
|
|
}
|
|
} else {
|
|
if(pPriv->hasTwoOverlays) {
|
|
if(pPriv->dualHeadMode) {
|
|
misc2 = 0x00;
|
|
misc1 = 0x04;
|
|
} else {
|
|
if(width > (limit * 2)) {
|
|
misc2 = 0x20;
|
|
} else {
|
|
misc2 = 0x10;
|
|
}
|
|
misc1 = 0x00;
|
|
}
|
|
} else if(pSiS->MiscFlags & MISC_SIS760ONEOVERLAY) {
|
|
if(width > (limit * 2)) {
|
|
misc2 = 0x20;
|
|
} else {
|
|
misc2 = 0x10;
|
|
}
|
|
misc1 = 0x00;
|
|
} else {
|
|
misc2 = 0x00;
|
|
misc1 = 0x04;
|
|
}
|
|
}
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc2, misc2, mask);
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc1, misc1, 0x04);
|
|
break;
|
|
|
|
case DISPMODE_SINGLE2:
|
|
if(pSiS->VGAEngine == SIS_300_VGA) {
|
|
if(pPriv->dualHeadMode) {
|
|
misc2 = 0x01;
|
|
misc1 = 0x04;
|
|
} else {
|
|
misc2 = 0x10;
|
|
misc1 = 0x00;
|
|
}
|
|
} else {
|
|
if(pPriv->hasTwoOverlays) {
|
|
if(pPriv->dualHeadMode) {
|
|
misc2 = 0x01;
|
|
misc1 = 0x04;
|
|
} else {
|
|
if(width > (limit * 2)) {
|
|
misc2 = 0x20;
|
|
} else {
|
|
misc2 = 0x10;
|
|
}
|
|
misc1 = 0x00;
|
|
}
|
|
} else if(pSiS->MiscFlags & MISC_SIS760ONEOVERLAY) {
|
|
if(width > (limit * 2)) {
|
|
misc2 = 0x20;
|
|
} else {
|
|
misc2 = 0x10;
|
|
}
|
|
misc1 = 0x00;
|
|
} else {
|
|
misc2 = 0x00;
|
|
misc1 = 0x04;
|
|
}
|
|
}
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc2, misc2, mask);
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc1, misc1, 0x04);
|
|
break;
|
|
|
|
case DISPMODE_MIRROR: /* This can only be on chips with 2 overlays */
|
|
default:
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, mask);
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x04, 0x04);
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, mask);
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x04, 0x04);
|
|
break;
|
|
}
|
|
|
|
} else { /* ----- disable linebuffer merge */
|
|
|
|
switch(pPriv->displayMode) {
|
|
|
|
case DISPMODE_SINGLE1:
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, mask);
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x04);
|
|
break;
|
|
|
|
case DISPMODE_SINGLE2:
|
|
if(pSiS->VGAEngine == SIS_300_VGA) {
|
|
if(pPriv->dualHeadMode) misc2 = 0x01;
|
|
else misc2 = 0x00;
|
|
} else {
|
|
if(pPriv->hasTwoOverlays) {
|
|
if(pPriv->dualHeadMode) misc2 = 0x01;
|
|
else misc2 = 0x00;
|
|
} else {
|
|
misc2 = 0x00;
|
|
}
|
|
}
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc2, misc2, mask);
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x04);
|
|
break;
|
|
|
|
case DISPMODE_MIRROR: /* This can only be on chips with 2 overlays */
|
|
default:
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, mask);
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x04);
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, mask);
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x04);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*********************************
|
|
* Select video format *
|
|
*********************************/
|
|
|
|
static __inline void
|
|
set_format(SISPtr pSiS, SISOverlayPtr pOverlay)
|
|
{
|
|
CARD8 fmt;
|
|
|
|
switch (pOverlay->pixelFormat){
|
|
case PIXEL_FMT_YV12:
|
|
case PIXEL_FMT_I420:
|
|
fmt = 0x0c;
|
|
break;
|
|
case PIXEL_FMT_YUY2:
|
|
fmt = 0x28;
|
|
break;
|
|
case PIXEL_FMT_UYVY:
|
|
fmt = 0x08;
|
|
break;
|
|
case PIXEL_FMT_YVYU:
|
|
fmt = 0x38;
|
|
break;
|
|
case PIXEL_FMT_NV12:
|
|
fmt = 0x4c;
|
|
break;
|
|
case PIXEL_FMT_NV21:
|
|
fmt = 0x5c;
|
|
break;
|
|
case PIXEL_FMT_RGB5: /* D[5:4] : 00 RGB555, 01 RGB 565 */
|
|
fmt = 0x00;
|
|
break;
|
|
case PIXEL_FMT_RGB6:
|
|
fmt = 0x10;
|
|
break;
|
|
default:
|
|
fmt = 0x00;
|
|
}
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc0, fmt, 0xfc);
|
|
}
|
|
|
|
/*********************************
|
|
* Set various video registers *
|
|
*********************************/
|
|
|
|
static __inline void
|
|
set_colorkey(SISPtr pSiS, CARD32 colorkey)
|
|
{
|
|
CARD8 r, g, b;
|
|
|
|
b = (CARD8)(colorkey & 0xFF);
|
|
g = (CARD8)((colorkey >> 8) & 0xFF);
|
|
r = (CARD8)((colorkey >> 16) & 0xFF);
|
|
|
|
setvideoreg(pSiS, Index_VI_Overlay_ColorKey_Blue_Min ,(CARD8)b);
|
|
setvideoreg(pSiS, Index_VI_Overlay_ColorKey_Green_Min ,(CARD8)g);
|
|
setvideoreg(pSiS, Index_VI_Overlay_ColorKey_Red_Min ,(CARD8)r);
|
|
|
|
setvideoreg(pSiS, Index_VI_Overlay_ColorKey_Blue_Max ,(CARD8)b);
|
|
setvideoreg(pSiS, Index_VI_Overlay_ColorKey_Green_Max ,(CARD8)g);
|
|
setvideoreg(pSiS, Index_VI_Overlay_ColorKey_Red_Max ,(CARD8)r);
|
|
}
|
|
|
|
static __inline void
|
|
set_chromakey(SISPtr pSiS, CARD32 chromamin, CARD32 chromamax)
|
|
{
|
|
CARD8 r1, g1, b1;
|
|
CARD8 r2, g2, b2;
|
|
|
|
b1 = (CARD8)(chromamin & 0xFF);
|
|
g1 = (CARD8)((chromamin >> 8) & 0xFF);
|
|
r1 = (CARD8)((chromamin >> 16) & 0xFF);
|
|
b2 = (CARD8)(chromamax & 0xFF);
|
|
g2 = (CARD8)((chromamax >> 8) & 0xFF);
|
|
r2 = (CARD8)((chromamax >> 16) & 0xFF);
|
|
|
|
setvideoreg(pSiS, Index_VI_Overlay_ChromaKey_Blue_V_Min ,(CARD8)b1);
|
|
setvideoreg(pSiS, Index_VI_Overlay_ChromaKey_Green_U_Min ,(CARD8)g1);
|
|
setvideoreg(pSiS, Index_VI_Overlay_ChromaKey_Red_Y_Min ,(CARD8)r1);
|
|
|
|
setvideoreg(pSiS, Index_VI_Overlay_ChromaKey_Blue_V_Max ,(CARD8)b2);
|
|
setvideoreg(pSiS, Index_VI_Overlay_ChromaKey_Green_U_Max ,(CARD8)g2);
|
|
setvideoreg(pSiS, Index_VI_Overlay_ChromaKey_Red_Y_Max ,(CARD8)r2);
|
|
}
|
|
|
|
static __inline void
|
|
set_brightness(SISPtr pSiS, CARD8 brightness)
|
|
{
|
|
setvideoreg(pSiS, Index_VI_Brightness, brightness);
|
|
}
|
|
|
|
static __inline void
|
|
set_contrast(SISPtr pSiS, CARD8 contrast)
|
|
{
|
|
setvideoregmask(pSiS, Index_VI_Contrast_Enh_Ctrl, contrast, 0x07);
|
|
}
|
|
|
|
/* 315 series and later only */
|
|
static __inline void
|
|
set_saturation(SISPtr pSiS, short saturation)
|
|
{
|
|
CARD8 temp = 0;
|
|
|
|
if(saturation < 0) {
|
|
temp |= 0x88;
|
|
saturation = -saturation;
|
|
}
|
|
temp |= (saturation & 0x07);
|
|
temp |= ((saturation & 0x07) << 4);
|
|
|
|
setvideoreg(pSiS, Index_VI_Saturation, temp);
|
|
}
|
|
|
|
/* 315 series and later only */
|
|
static __inline void
|
|
set_hue(SISPtr pSiS, CARD8 hue)
|
|
{
|
|
setvideoregmask(pSiS, Index_VI_Hue, (hue & 0x08) ? (hue ^ 0x07) : hue, 0x0F);
|
|
}
|
|
|
|
static __inline void
|
|
set_disablegfx(SISPtr pSiS, Bool mybool, SISOverlayPtr pOverlay)
|
|
{
|
|
/* This is not supported on M65x, 65x (x>0) or later */
|
|
/* For CRT1 ONLY!!! */
|
|
if((!(pSiS->ChipFlags & SiSCF_Is65x)) &&
|
|
(pSiS->Chipset != PCI_CHIP_SIS660) &&
|
|
(pSiS->Chipset != PCI_CHIP_SIS340) &&
|
|
(pSiS->Chipset != PCI_CHIP_XGIXG20) &&
|
|
(pSiS->Chipset != PCI_CHIP_XGIXG40)) {
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc2, mybool ? 0x04 : 0x00, 0x04);
|
|
if(mybool) pOverlay->keyOP = VI_ROP_Always;
|
|
}
|
|
}
|
|
|
|
static __inline void
|
|
set_disablegfxlr(SISPtr pSiS, Bool mybool, SISOverlayPtr pOverlay)
|
|
{
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc1, mybool ? 0x01 : 0x00, 0x01);
|
|
if(mybool) pOverlay->keyOP = VI_ROP_Always;
|
|
}
|
|
|
|
#ifdef SIS_CP
|
|
SIS_CP_VIDEO_SUBS
|
|
#endif
|
|
|
|
/*********************************
|
|
* Set main overlay registers *
|
|
*********************************/
|
|
|
|
static void
|
|
set_overlay(SISPtr pSiS, SISOverlayPtr pOverlay, SISPortPrivPtr pPriv, int index, int iscrt2)
|
|
{
|
|
CARD8 h_over, v_over;
|
|
CARD16 top, bottom, left, right, pitch = 0;
|
|
CARD16 screenX, screenY;
|
|
CARD32 PSY;
|
|
int modeflags, totalPixels, confactor, sample, watchdog = 0;
|
|
|
|
#ifdef SISMERGED
|
|
if(pSiS->MergedFB && iscrt2) {
|
|
screenX = pOverlay->currentmode2->HDisplay;
|
|
screenY = pOverlay->currentmode2->VDisplay;
|
|
modeflags = pOverlay->currentmode2->Flags;
|
|
top = pOverlay->dstBox2.y1;
|
|
bottom = pOverlay->dstBox2.y2;
|
|
left = pOverlay->dstBox2.x1;
|
|
right = pOverlay->dstBox2.x2;
|
|
pitch = pOverlay->pitch2 >> pPriv->shiftValue;
|
|
} else {
|
|
#endif
|
|
screenX = pOverlay->currentmode->HDisplay;
|
|
screenY = pOverlay->currentmode->VDisplay;
|
|
modeflags = pOverlay->currentmode->Flags;
|
|
top = pOverlay->dstBox.y1;
|
|
bottom = pOverlay->dstBox.y2;
|
|
left = pOverlay->dstBox.x1;
|
|
right = pOverlay->dstBox.x2;
|
|
pitch = pOverlay->pitch >> pPriv->shiftValue;
|
|
#ifdef SISMERGED
|
|
}
|
|
#endif
|
|
|
|
if(bottom > screenY) bottom = screenY;
|
|
if(right > screenX) right = screenX;
|
|
|
|
/* calculate contrast factor */
|
|
totalPixels = (right - left) * (bottom - top);
|
|
confactor = (totalPixels - 10000) / 20000;
|
|
if(confactor > 3) confactor = 3;
|
|
switch(confactor) {
|
|
case 1: sample = 4096 << 10; break;
|
|
case 2:
|
|
case 3: sample = 8192 << 10; break;
|
|
default: sample = 2048 << 10;
|
|
}
|
|
sample /= totalPixels;
|
|
confactor <<= 6;
|
|
|
|
/* Correct coordinates for doublescan/interlace modes */
|
|
if( (modeflags & V_DBLSCAN) &&
|
|
(!((pPriv->bridgeIsSlave || iscrt2) && (pSiS->MiscFlags & MISC_STNMODE))) ) {
|
|
/* DoubleScan modes require Y coordinates * 2 */
|
|
top <<= 1;
|
|
bottom <<= 1;
|
|
} else if(modeflags & V_INTERLACE) {
|
|
/* Interlace modes require Y coordinates / 2 */
|
|
top >>= 1;
|
|
bottom >>= 1;
|
|
}
|
|
|
|
h_over = (((left >> 8) & 0x0f) | ((right >> 4) & 0xf0));
|
|
v_over = (((top >> 8) & 0x0f) | ((bottom >> 4) & 0xf0));
|
|
|
|
/* set line buffer size */
|
|
#ifdef SISMERGED
|
|
if(pSiS->MergedFB && iscrt2) {
|
|
setvideoreg(pSiS, Index_VI_Line_Buffer_Size, (CARD8)pOverlay->lineBufSize2);
|
|
if(pPriv->is340 || pPriv->is761 || pPriv->isXGI) {
|
|
setvideoreg(pSiS, Index_VI_Line_Buffer_Size_High, (CARD8)(pOverlay->lineBufSize2 >> 8));
|
|
}
|
|
} else {
|
|
#endif
|
|
setvideoreg(pSiS, Index_VI_Line_Buffer_Size, (CARD8)pOverlay->lineBufSize);
|
|
if(pPriv->is340 || pPriv->is761 || pPriv->isXGI) {
|
|
setvideoreg(pSiS, Index_VI_Line_Buffer_Size_High, (CARD8)(pOverlay->lineBufSize >> 8));
|
|
}
|
|
#ifdef SISMERGED
|
|
}
|
|
#endif
|
|
|
|
/* set color key mode */
|
|
setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, pOverlay->keyOP, 0x0f);
|
|
|
|
/* We don't have to wait for vertical retrace in all cases */
|
|
if(pPriv->mustwait) {
|
|
if(pSiS->VGAEngine == SIS_315_VGA) {
|
|
|
|
if(index) {
|
|
CARD16 mytop = getvideoreg(pSiS, Index_VI_Win_Ver_Disp_Start_Low);
|
|
mytop |= ((getvideoreg(pSiS, Index_VI_Win_Ver_Over) & 0x0f) << 8);
|
|
pOverlay->oldtop = mytop;
|
|
watchdog = 0xffff;
|
|
if(mytop < screenY - 2) {
|
|
do {
|
|
watchdog = get_scanline_CRT2(pSiS, pPriv);
|
|
} while((watchdog <= mytop) || (watchdog >= screenY));
|
|
}
|
|
pOverlay->oldLine = watchdog;
|
|
}
|
|
|
|
} else {
|
|
|
|
watchdog = WATCHDOG_DELAY;
|
|
while(pOverlay->VBlankActiveFunc(pSiS, pPriv) && --watchdog);
|
|
watchdog = WATCHDOG_DELAY;
|
|
while((!pOverlay->VBlankActiveFunc(pSiS, pPriv)) && --watchdog);
|
|
|
|
}
|
|
}
|
|
|
|
/* Unlock address registers */
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x20, 0x20);
|
|
|
|
/* Set destination window position */
|
|
setvideoreg(pSiS, Index_VI_Win_Hor_Disp_Start_Low, (CARD8)left);
|
|
setvideoreg(pSiS, Index_VI_Win_Hor_Disp_End_Low, (CARD8)right);
|
|
setvideoreg(pSiS, Index_VI_Win_Hor_Over, (CARD8)h_over);
|
|
|
|
setvideoreg(pSiS, Index_VI_Win_Ver_Disp_Start_Low, (CARD8)top);
|
|
setvideoreg(pSiS, Index_VI_Win_Ver_Disp_End_Low, (CARD8)bottom);
|
|
setvideoreg(pSiS, Index_VI_Win_Ver_Over, (CARD8)v_over);
|
|
|
|
/* Contrast factor */
|
|
setvideoregmask(pSiS, Index_VI_Contrast_Enh_Ctrl, (CARD8)confactor, 0xc0);
|
|
setvideoreg(pSiS, Index_VI_Contrast_Factor, sample);
|
|
|
|
/* Set Y buf pitch */
|
|
setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Pitch_Low, (CARD8)(pitch));
|
|
setvideoregmask(pSiS, Index_VI_Disp_Y_UV_Buf_Pitch_Middle, (CARD8)(pitch >> 8), 0x0f);
|
|
|
|
/* Set Y start address */
|
|
#ifdef SISMERGED
|
|
if(pSiS->MergedFB && iscrt2) {
|
|
PSY = pOverlay->PSY2;
|
|
} else
|
|
#endif
|
|
PSY = pOverlay->PSY;
|
|
|
|
setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Start_Low, (CARD8)(PSY));
|
|
setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Start_Middle, (CARD8)(PSY >> 8));
|
|
setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Start_High, (CARD8)(PSY >> 16));
|
|
|
|
/* Set 315 series overflow bits for Y plane */
|
|
if(pSiS->VGAEngine == SIS_315_VGA) {
|
|
setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Pitch_High, (CARD8)(pitch >> 12));
|
|
setvideoreg(pSiS, Index_VI_Y_Buf_Start_Over, ((CARD8)(PSY >> 24) & 0x03));
|
|
}
|
|
|
|
/* Set U/V data if using planar formats */
|
|
if(pOverlay->planar) {
|
|
|
|
CARD32 PSU = pOverlay->PSU;
|
|
CARD32 PSV = pOverlay->PSV;
|
|
|
|
#ifdef SISMERGED
|
|
if(pSiS->MergedFB && iscrt2) {
|
|
PSU = pOverlay->PSU2;
|
|
PSV = pOverlay->PSV2;
|
|
}
|
|
#endif
|
|
|
|
if(pOverlay->planar_shiftpitch) pitch >>= 1;
|
|
|
|
/* Set U/V pitch */
|
|
setvideoreg(pSiS, Index_VI_Disp_UV_Buf_Pitch_Low, (CARD8)pitch);
|
|
setvideoregmask(pSiS, Index_VI_Disp_Y_UV_Buf_Pitch_Middle, (CARD8)(pitch >> 4), 0xf0);
|
|
|
|
/* Set U/V start address */
|
|
setvideoreg(pSiS, Index_VI_U_Buf_Start_Low, (CARD8)PSU);
|
|
setvideoreg(pSiS, Index_VI_U_Buf_Start_Middle,(CARD8)(PSU >> 8));
|
|
setvideoreg(pSiS, Index_VI_U_Buf_Start_High, (CARD8)(PSU >> 16));
|
|
|
|
setvideoreg(pSiS, Index_VI_V_Buf_Start_Low, (CARD8)PSV);
|
|
setvideoreg(pSiS, Index_VI_V_Buf_Start_Middle,(CARD8)(PSV >> 8));
|
|
setvideoreg(pSiS, Index_VI_V_Buf_Start_High, (CARD8)(PSV >> 16));
|
|
|
|
/* 315 series overflow bits */
|
|
if(pSiS->VGAEngine == SIS_315_VGA) {
|
|
setvideoreg(pSiS, Index_VI_Disp_UV_Buf_Pitch_High, (CARD8)(pitch >> 12));
|
|
setvideoreg(pSiS, Index_VI_U_Buf_Start_Over, ((CARD8)(PSU >> 24) & 0x03));
|
|
if(pPriv->is661741760) {
|
|
setvideoregmask(pSiS, Index_VI_V_Buf_Start_Over, ((CARD8)(PSV >> 24) & 0x03), 0xc3);
|
|
} else {
|
|
setvideoreg(pSiS, Index_VI_V_Buf_Start_Over, ((CARD8)(PSV >> 24) & 0x03));
|
|
}
|
|
}
|
|
}
|
|
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc1, pOverlay->bobEnable, 0x1a);
|
|
|
|
/* Lock the address registers */
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x20);
|
|
|
|
/* Set scale factor */
|
|
#ifdef SISMERGED
|
|
if(pSiS->MergedFB && iscrt2) {
|
|
setvideoreg(pSiS, Index_VI_Hor_Post_Up_Scale_Low, (CARD8)(pOverlay->HUSF2));
|
|
setvideoreg(pSiS, Index_VI_Hor_Post_Up_Scale_High,(CARD8)((pOverlay->HUSF2) >> 8));
|
|
setvideoreg(pSiS, Index_VI_Ver_Up_Scale_Low, (CARD8)(pOverlay->VUSF2));
|
|
setvideoreg(pSiS, Index_VI_Ver_Up_Scale_High, (CARD8)((pOverlay->VUSF2) >> 8));
|
|
|
|
setvideoregmask(pSiS, Index_VI_Scale_Control, (pOverlay->IntBit2 << 3) |
|
|
(pOverlay->wHPre2), 0x7f);
|
|
|
|
if(pPriv->havetapscaler) {
|
|
if((pOverlay->tap_scale2 != pOverlay->tap_scale2_old) || pPriv->mustresettap2) {
|
|
set_dda_regs(pSiS, pOverlay->tap_scale2);
|
|
pOverlay->tap_scale2_old = pOverlay->tap_scale2;
|
|
pPriv->mustresettap2 = FALSE;
|
|
}
|
|
}
|
|
} else {
|
|
#endif
|
|
setvideoreg(pSiS, Index_VI_Hor_Post_Up_Scale_Low, (CARD8)(pOverlay->HUSF));
|
|
setvideoreg(pSiS, Index_VI_Hor_Post_Up_Scale_High,(CARD8)((pOverlay->HUSF) >> 8));
|
|
setvideoreg(pSiS, Index_VI_Ver_Up_Scale_Low, (CARD8)(pOverlay->VUSF));
|
|
setvideoreg(pSiS, Index_VI_Ver_Up_Scale_High, (CARD8)((pOverlay->VUSF) >> 8));
|
|
|
|
setvideoregmask(pSiS, Index_VI_Scale_Control, (pOverlay->IntBit << 3) |
|
|
(pOverlay->wHPre), 0x7f);
|
|
if(pPriv->havetapscaler) {
|
|
if((pOverlay->tap_scale != pOverlay->tap_scale_old) || pPriv->mustresettap) {
|
|
set_dda_regs(pSiS, pOverlay->tap_scale);
|
|
pOverlay->tap_scale_old = pOverlay->tap_scale;
|
|
pPriv->mustresettap = FALSE;
|
|
}
|
|
}
|
|
#ifdef SISMERGED
|
|
}
|
|
#endif
|
|
|
|
}
|
|
|
|
/*********************************
|
|
* Shut down overlay *
|
|
*********************************/
|
|
|
|
/* Overlay MUST NOT be switched off while beam is over it */
|
|
static void
|
|
close_overlay(SISPtr pSiS, SISPortPrivPtr pPriv)
|
|
{
|
|
int watchdog;
|
|
|
|
if(!pPriv->overlayStatus) return;
|
|
|
|
pPriv->overlayStatus = FALSE;
|
|
|
|
pPriv->mustresettap = TRUE;
|
|
#ifdef SISMERGED
|
|
pPriv->mustresettap2 = TRUE;
|
|
#endif
|
|
|
|
if(pPriv->displayMode & (DISPMODE_MIRROR | DISPMODE_SINGLE2)) {
|
|
|
|
/* CRT2: MIRROR or SINGLE2
|
|
* 1 overlay: Uses overlay 0
|
|
* 2 overlays: Uses Overlay 1 if MIRROR or DUAL HEAD
|
|
* Uses Overlay 0 if SINGLE2 and not DUAL HEAD
|
|
*/
|
|
|
|
if(pPriv->hasTwoOverlays) {
|
|
|
|
if((pPriv->dualHeadMode) || (pPriv->displayMode == DISPMODE_MIRROR)) {
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, 0x01);
|
|
} else {
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0x01);
|
|
}
|
|
|
|
} else if(pPriv->displayMode == DISPMODE_SINGLE2) {
|
|
|
|
#ifdef SISDUALHEAD
|
|
if(pPriv->dualHeadMode) {
|
|
/* Check if overlay already grabbed by other head */
|
|
if(!(getsrreg(pSiS, 0x06) & 0x40)) return;
|
|
}
|
|
#endif
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0x01);
|
|
|
|
}
|
|
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x01);
|
|
|
|
watchdog = WATCHDOG_DELAY;
|
|
while((!vblank_active_CRT2(pSiS, pPriv)) && --watchdog);
|
|
watchdog = WATCHDOG_DELAY;
|
|
while(vblank_active_CRT2(pSiS, pPriv) && --watchdog);
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02);
|
|
watchdog = WATCHDOG_DELAY;
|
|
while((!vblank_active_CRT2(pSiS, pPriv)) && --watchdog);
|
|
watchdog = WATCHDOG_DELAY;
|
|
while(vblank_active_CRT2(pSiS, pPriv) && --watchdog);
|
|
|
|
#ifdef SIS_CP
|
|
SIS_CP_RESET_CP
|
|
#endif
|
|
|
|
}
|
|
|
|
if(pPriv->displayMode & (DISPMODE_SINGLE1 | DISPMODE_MIRROR)) {
|
|
|
|
/* CRT1: Always uses overlay 0
|
|
*/
|
|
|
|
#ifdef SISDUALHEAD
|
|
if(pPriv->dualHeadMode) {
|
|
if(!pPriv->hasTwoOverlays) {
|
|
/* Check if overlay already grabbed by other head */
|
|
if(getsrreg(pSiS, 0x06) & 0x40) return;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0x05);
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x01);
|
|
|
|
watchdog = WATCHDOG_DELAY;
|
|
while((!vblank_active_CRT1(pSiS, pPriv)) && --watchdog);
|
|
watchdog = WATCHDOG_DELAY;
|
|
while(vblank_active_CRT1(pSiS, pPriv) && --watchdog);
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02);
|
|
watchdog = WATCHDOG_DELAY;
|
|
while((!vblank_active_CRT1(pSiS, pPriv)) && --watchdog);
|
|
watchdog = WATCHDOG_DELAY;
|
|
while(vblank_active_CRT1(pSiS, pPriv) && --watchdog);
|
|
|
|
}
|
|
}
|
|
|
|
/*********************************
|
|
* DisplayVideo() *
|
|
*********************************/
|
|
|
|
static void
|
|
SISDisplayVideo(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
#ifdef SISDUALHEAD
|
|
SISEntPtr pSiSEnt = pSiS->entityPrivate;
|
|
#endif
|
|
short srcPitch = pPriv->srcPitch;
|
|
short height = pPriv->height;
|
|
UShort screenwidth;
|
|
SISOverlayRec overlay;
|
|
int srcOffsetX = 0, srcOffsetY = 0;
|
|
int sx = 0, sy = 0, watchdog;
|
|
int index = 0, iscrt2 = 0;
|
|
#ifdef SISMERGED
|
|
UChar temp;
|
|
UShort screen2width = 0;
|
|
int srcOffsetX2 = 0, srcOffsetY2 = 0;
|
|
int sx2 = 0, sy2 = 0;
|
|
#endif
|
|
|
|
/* Determine whether we have two overlays or only one */
|
|
set_hastwooverlays(pSiS, pPriv);
|
|
|
|
pPriv->NoOverlay = FALSE;
|
|
#ifdef SISDUALHEAD
|
|
if(pPriv->dualHeadMode) {
|
|
if(!pPriv->hasTwoOverlays) {
|
|
if(pSiS->SecondHead) {
|
|
if(pSiSEnt->curxvcrtnum != 0) {
|
|
if(pPriv->overlayStatus) {
|
|
close_overlay(pSiS, pPriv);
|
|
}
|
|
pPriv->NoOverlay = TRUE;
|
|
return;
|
|
}
|
|
} else {
|
|
if(pSiSEnt->curxvcrtnum != 1) {
|
|
if(pPriv->overlayStatus) {
|
|
close_overlay(pSiS, pPriv);
|
|
}
|
|
pPriv->NoOverlay = TRUE;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* setup dispmode (MIRROR, SINGLEx) */
|
|
set_dispmode(pScrn, pPriv);
|
|
|
|
/* Check if overlay is supported with current mode */
|
|
#ifdef SISMERGED
|
|
if(!pSiS->MergedFB) {
|
|
#endif
|
|
if( ((pPriv->displayMode & DISPMODE_MIRROR) &&
|
|
((pSiS->MiscFlags & (MISC_CRT1OVERLAY|MISC_CRT2OVERLAY)) != (MISC_CRT1OVERLAY|MISC_CRT2OVERLAY))) ||
|
|
((pPriv->displayMode & DISPMODE_SINGLE1) &&
|
|
(!(pSiS->MiscFlags & MISC_CRT1OVERLAY))) ||
|
|
((pPriv->displayMode & DISPMODE_SINGLE2) &&
|
|
(!(pSiS->MiscFlags & MISC_CRT2OVERLAY))) ) {
|
|
if(pPriv->overlayStatus) {
|
|
close_overlay(pSiS, pPriv);
|
|
}
|
|
pPriv->NoOverlay = TRUE;
|
|
return;
|
|
}
|
|
#ifdef SISMERGED
|
|
}
|
|
#endif
|
|
|
|
memset(&overlay, 0, sizeof(overlay));
|
|
|
|
overlay.pixelFormat = pPriv->id;
|
|
overlay.pitch = overlay.origPitch = srcPitch;
|
|
if(pPriv->usechromakey) {
|
|
overlay.keyOP = (pPriv->insidechromakey) ? VI_ROP_ChromaKey : VI_ROP_NotChromaKey;
|
|
} else {
|
|
overlay.keyOP = VI_ROP_DestKey;
|
|
}
|
|
|
|
#ifdef SISDEINT
|
|
switch(pPriv->deinterlacemethod) {
|
|
case 1:
|
|
overlay.bobEnable = 0x02;
|
|
/* overlay.bobEnable |= (pPriv->currentBuf) ? 0x00 : 0x10; */
|
|
break;
|
|
case 2:
|
|
overlay.bobEnable = 0x08;
|
|
/* overlay.bobEnable |= (pPriv->currentBuf) ? 0x00 : 0x10; */
|
|
break;
|
|
case 3:
|
|
overlay.bobEnable = 0x0a;
|
|
/* overlay.bobEnable |= (pPriv->currentBuf) ? 0x00 : 0x10; */
|
|
break;
|
|
default:
|
|
#endif
|
|
overlay.bobEnable = 0x00; /* Disable BOB de-interlacer */
|
|
#ifdef SISDEINT
|
|
}
|
|
#endif
|
|
|
|
#ifdef SISMERGED
|
|
if(pSiS->MergedFB) {
|
|
overlay.DoFirst = TRUE;
|
|
overlay.DoSecond = TRUE;
|
|
overlay.pitch2 = overlay.origPitch;
|
|
overlay.currentmode = ((SiSMergedDisplayModePtr)pSiS->CurrentLayout.mode->Private)->CRT1;
|
|
overlay.currentmode2 = ((SiSMergedDisplayModePtr)pSiS->CurrentLayout.mode->Private)->CRT2;
|
|
overlay.SCREENheight = overlay.currentmode->VDisplay;
|
|
overlay.SCREENheight2 = overlay.currentmode2->VDisplay;
|
|
screenwidth = overlay.currentmode->HDisplay;
|
|
screen2width = overlay.currentmode2->HDisplay;
|
|
overlay.dstBox.x1 = pPriv->drw_x - pSiS->CRT1frameX0;
|
|
overlay.dstBox.x2 = overlay.dstBox.x1 + pPriv->drw_w;
|
|
overlay.dstBox.y1 = pPriv->drw_y - pSiS->CRT1frameY0;
|
|
overlay.dstBox.y2 = overlay.dstBox.y1 + pPriv->drw_h;
|
|
overlay.dstBox2.x1 = pPriv->drw_x - pSiS->CRT2pScrn->frameX0;
|
|
overlay.dstBox2.x2 = overlay.dstBox2.x1 + pPriv->drw_w;
|
|
overlay.dstBox2.y1 = pPriv->drw_y - pSiS->CRT2pScrn->frameY0;
|
|
overlay.dstBox2.y2 = overlay.dstBox2.y1 + pPriv->drw_h;
|
|
} else {
|
|
#endif
|
|
overlay.currentmode = pSiS->CurrentLayout.mode;
|
|
overlay.SCREENheight = overlay.currentmode->VDisplay;
|
|
screenwidth = overlay.currentmode->HDisplay;
|
|
overlay.dstBox.x1 = pPriv->drw_x - pScrn->frameX0;
|
|
overlay.dstBox.x2 = pPriv->drw_x + pPriv->drw_w - pScrn->frameX0;
|
|
overlay.dstBox.y1 = pPriv->drw_y - pScrn->frameY0;
|
|
overlay.dstBox.y2 = pPriv->drw_y + pPriv->drw_h - pScrn->frameY0;
|
|
#ifdef SISMERGED
|
|
}
|
|
#endif
|
|
|
|
/* Note: x2/y2 is actually real coordinate + 1 */
|
|
|
|
if((overlay.dstBox.x1 >= overlay.dstBox.x2) ||
|
|
(overlay.dstBox.y1 >= overlay.dstBox.y2)) {
|
|
#ifdef SISMERGED
|
|
if(pSiS->MergedFB) overlay.DoFirst = FALSE;
|
|
else
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
if((overlay.dstBox.x2 <= 0) || (overlay.dstBox.y2 <= 0)) {
|
|
#ifdef SISMERGED
|
|
if(pSiS->MergedFB) overlay.DoFirst = FALSE;
|
|
else
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
if((overlay.dstBox.x1 >= screenwidth) || (overlay.dstBox.y1 >= overlay.SCREENheight)) {
|
|
#ifdef SISMERGED
|
|
if(pSiS->MergedFB) overlay.DoFirst = FALSE;
|
|
else
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
#ifdef SISMERGED
|
|
if(pSiS->MergedFB) {
|
|
/* Check if dotclock is within limits for CRT1 */
|
|
if(pPriv->displayMode & (DISPMODE_SINGLE1 | DISPMODE_MIRROR)) {
|
|
if(!(pSiS->MiscFlags & MISC_CRT1OVERLAY)) {
|
|
overlay.DoFirst = FALSE;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if(overlay.dstBox.x1 < 0) {
|
|
srcOffsetX = pPriv->src_w * (-overlay.dstBox.x1) / pPriv->drw_w;
|
|
overlay.dstBox.x1 = 0;
|
|
}
|
|
if(overlay.dstBox.y1 < 0) {
|
|
srcOffsetY = pPriv->src_h * (-overlay.dstBox.y1) / pPriv->drw_h;
|
|
overlay.dstBox.y1 = 0;
|
|
}
|
|
|
|
if((overlay.dstBox.x1 >= overlay.dstBox.x2 - 2) ||
|
|
(overlay.dstBox.x1 >= screenwidth - 2) ||
|
|
(overlay.dstBox.y1 >= overlay.dstBox.y2)) {
|
|
#ifdef SISMERGED
|
|
if(pSiS->MergedFB) overlay.DoFirst = FALSE;
|
|
else
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
#ifdef SISMERGED
|
|
if(pSiS->MergedFB) {
|
|
if((overlay.dstBox2.x2 <= 0) || (overlay.dstBox2.y2 <= 0))
|
|
overlay.DoSecond = FALSE;
|
|
|
|
if((overlay.dstBox2.x1 >= screen2width) || (overlay.dstBox2.y1 >= overlay.SCREENheight2))
|
|
overlay.DoSecond = FALSE;
|
|
|
|
if(overlay.dstBox2.x1 < 0) {
|
|
srcOffsetX2 = pPriv->src_w * (-overlay.dstBox2.x1) / pPriv->drw_w;
|
|
overlay.dstBox2.x1 = 0;
|
|
}
|
|
|
|
if(overlay.dstBox2.y1 < 0) {
|
|
srcOffsetY2 = pPriv->src_h * (-overlay.dstBox2.y1) / pPriv->drw_h;
|
|
overlay.dstBox2.y1 = 0;
|
|
}
|
|
|
|
if((overlay.dstBox2.x1 >= overlay.dstBox2.x2 - 2) ||
|
|
(overlay.dstBox2.x1 >= screen2width - 2) ||
|
|
(overlay.dstBox2.y1 >= overlay.dstBox2.y2))
|
|
overlay.DoSecond = FALSE;
|
|
|
|
/* Check if dotclock is within limits for CRT2 */
|
|
if(pPriv->displayMode & (DISPMODE_SINGLE2 | DISPMODE_MIRROR)) {
|
|
if(!(pSiS->MiscFlags & MISC_CRT2OVERLAY)) {
|
|
overlay.DoSecond = FALSE;
|
|
}
|
|
}
|
|
|
|
/* If neither overlay is to be displayed, disable them if they are currently enabled */
|
|
if((!overlay.DoFirst) && (!overlay.DoSecond)) {
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0x05);
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x01);
|
|
temp = getvideoreg(pSiS,Index_VI_Control_Misc0);
|
|
if(temp & 0x02) {
|
|
watchdog = WATCHDOG_DELAY;
|
|
if(pPriv->hasTwoOverlays) {
|
|
while((!vblank_active_CRT1(pSiS, pPriv)) && --watchdog);
|
|
watchdog = WATCHDOG_DELAY;
|
|
while(vblank_active_CRT1(pSiS, pPriv) && --watchdog);
|
|
} else {
|
|
temp = getsrreg(pSiS, 0x06);
|
|
if(!(temp & 0x40)) {
|
|
while((!vblank_active_CRT1(pSiS, pPriv)) && --watchdog);
|
|
watchdog = WATCHDOG_DELAY;
|
|
while(vblank_active_CRT1(pSiS, pPriv) && --watchdog);
|
|
} else {
|
|
while((!vblank_active_CRT2(pSiS, pPriv)) && --watchdog);
|
|
watchdog = WATCHDOG_DELAY;
|
|
while(vblank_active_CRT2(pSiS, pPriv) && --watchdog);
|
|
}
|
|
}
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02);
|
|
}
|
|
if(pPriv->hasTwoOverlays) {
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, 0x01);
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x01);
|
|
temp = getvideoreg(pSiS,Index_VI_Control_Misc0);
|
|
if(temp & 0x02) {
|
|
watchdog = WATCHDOG_DELAY;
|
|
while((!vblank_active_CRT2(pSiS, pPriv)) && --watchdog);
|
|
watchdog = WATCHDOG_DELAY;
|
|
while(vblank_active_CRT2(pSiS, pPriv) && --watchdog);
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02);
|
|
}
|
|
}
|
|
pPriv->overlayStatus = FALSE;
|
|
return;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
switch(pPriv->id) {
|
|
|
|
case PIXEL_FMT_YV12:
|
|
overlay.planar = 1;
|
|
overlay.planar_shiftpitch = 1;
|
|
#ifdef SISMERGED
|
|
if((!pSiS->MergedFB) || (overlay.DoFirst)) {
|
|
#endif
|
|
sx = (pPriv->src_x + srcOffsetX) & ~7;
|
|
sy = (pPriv->src_y + srcOffsetY) & ~1;
|
|
overlay.PSY = pPriv->bufAddr[pPriv->currentBuf] + sx + sy*srcPitch;
|
|
overlay.PSV = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch + ((sx + sy*srcPitch/2) >> 1);
|
|
overlay.PSU = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch*5/4 + ((sx + sy*srcPitch/2) >> 1);
|
|
overlay.PSY += FBOFFSET;
|
|
overlay.PSV += FBOFFSET;
|
|
overlay.PSU += FBOFFSET;
|
|
overlay.PSY >>= pPriv->shiftValue;
|
|
overlay.PSV >>= pPriv->shiftValue;
|
|
overlay.PSU >>= pPriv->shiftValue;
|
|
#ifdef SISMERGED
|
|
}
|
|
if((pSiS->MergedFB) && (overlay.DoSecond)) {
|
|
sx2 = (pPriv->src_x + srcOffsetX2) & ~7;
|
|
sy2 = (pPriv->src_y + srcOffsetY2) & ~1;
|
|
overlay.PSY2 = pPriv->bufAddr[pPriv->currentBuf] + sx2 + sy2*srcPitch;
|
|
overlay.PSV2 = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch + ((sx2 + sy2*srcPitch/2) >> 1);
|
|
overlay.PSU2 = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch*5/4 + ((sx2 + sy2*srcPitch/2) >> 1);
|
|
overlay.PSY2 += FBOFFSET;
|
|
overlay.PSV2 += FBOFFSET;
|
|
overlay.PSU2 += FBOFFSET;
|
|
overlay.PSY2 >>= pPriv->shiftValue;
|
|
overlay.PSV2 >>= pPriv->shiftValue;
|
|
overlay.PSU2 >>= pPriv->shiftValue;
|
|
}
|
|
#endif
|
|
break;
|
|
|
|
case PIXEL_FMT_I420:
|
|
overlay.planar = 1;
|
|
overlay.planar_shiftpitch = 1;
|
|
#ifdef SISMERGED
|
|
if((!pSiS->MergedFB) || (overlay.DoFirst)) {
|
|
#endif
|
|
sx = (pPriv->src_x + srcOffsetX) & ~7;
|
|
sy = (pPriv->src_y + srcOffsetY) & ~1;
|
|
overlay.PSY = pPriv->bufAddr[pPriv->currentBuf] + sx + sy*srcPitch;
|
|
overlay.PSV = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch*5/4 + ((sx + sy*srcPitch/2) >> 1);
|
|
overlay.PSU = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch + ((sx + sy*srcPitch/2) >> 1);
|
|
overlay.PSY += FBOFFSET;
|
|
overlay.PSV += FBOFFSET;
|
|
overlay.PSU += FBOFFSET;
|
|
overlay.PSY >>= pPriv->shiftValue;
|
|
overlay.PSV >>= pPriv->shiftValue;
|
|
overlay.PSU >>= pPriv->shiftValue;
|
|
#ifdef SISMERGED
|
|
}
|
|
if((pSiS->MergedFB) && (overlay.DoSecond)) {
|
|
sx2 = (pPriv->src_x + srcOffsetX2) & ~7;
|
|
sy2 = (pPriv->src_y + srcOffsetY2) & ~1;
|
|
overlay.PSY2 = pPriv->bufAddr[pPriv->currentBuf] + sx2 + sy2*srcPitch;
|
|
overlay.PSV2 = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch*5/4 + ((sx2 + sy2*srcPitch/2) >> 1);
|
|
overlay.PSU2 = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch + ((sx2 + sy2*srcPitch/2) >> 1);
|
|
overlay.PSY2 += FBOFFSET;
|
|
overlay.PSV2 += FBOFFSET;
|
|
overlay.PSU2 += FBOFFSET;
|
|
overlay.PSY2 >>= pPriv->shiftValue;
|
|
overlay.PSV2 >>= pPriv->shiftValue;
|
|
overlay.PSU2 >>= pPriv->shiftValue;
|
|
}
|
|
#endif
|
|
break;
|
|
|
|
case PIXEL_FMT_NV12:
|
|
case PIXEL_FMT_NV21:
|
|
overlay.planar = 1;
|
|
overlay.planar_shiftpitch = 0;
|
|
#ifdef SISMERGED
|
|
if((!pSiS->MergedFB) || (overlay.DoFirst)) {
|
|
#endif
|
|
sx = (pPriv->src_x + srcOffsetX) & ~7;
|
|
sy = (pPriv->src_y + srcOffsetY) & ~1;
|
|
overlay.PSY = pPriv->bufAddr[pPriv->currentBuf] + sx + sy*srcPitch;
|
|
overlay.PSV = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch + ((sx + sy*srcPitch/2) >> 1);
|
|
overlay.PSY += FBOFFSET;
|
|
overlay.PSV += FBOFFSET;
|
|
overlay.PSY >>= pPriv->shiftValue;
|
|
overlay.PSV >>= pPriv->shiftValue;
|
|
overlay.PSU = overlay.PSV;
|
|
#ifdef SISMERGED
|
|
}
|
|
if((pSiS->MergedFB) && (overlay.DoSecond)) {
|
|
sx2 = (pPriv->src_x + srcOffsetX2) & ~7;
|
|
sy2 = (pPriv->src_y + srcOffsetY2) & ~1;
|
|
overlay.PSY2 = pPriv->bufAddr[pPriv->currentBuf] + sx2 + sy2*srcPitch;
|
|
overlay.PSV2 = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch + ((sx2 + sy2*srcPitch/2) >> 1);
|
|
overlay.PSY2 += FBOFFSET;
|
|
overlay.PSV2 += FBOFFSET;
|
|
overlay.PSY2 >>= pPriv->shiftValue;
|
|
overlay.PSV2 >>= pPriv->shiftValue;
|
|
overlay.PSU2 = overlay.PSV2;
|
|
}
|
|
#endif
|
|
break;
|
|
|
|
case PIXEL_FMT_YUY2:
|
|
case PIXEL_FMT_UYVY:
|
|
case PIXEL_FMT_YVYU:
|
|
case PIXEL_FMT_RGB6:
|
|
case PIXEL_FMT_RGB5:
|
|
default:
|
|
overlay.planar = 0;
|
|
#ifdef SISMERGED
|
|
if((!pSiS->MergedFB) || (overlay.DoFirst)) {
|
|
#endif
|
|
sx = (pPriv->src_x + srcOffsetX) & ~1;
|
|
sy = (pPriv->src_y + srcOffsetY);
|
|
overlay.PSY = (pPriv->bufAddr[pPriv->currentBuf] + sx*2 + sy*srcPitch);
|
|
overlay.PSY += FBOFFSET;
|
|
overlay.PSY >>= pPriv->shiftValue;
|
|
#ifdef SISMERGED
|
|
}
|
|
if((pSiS->MergedFB) && (overlay.DoSecond)) {
|
|
sx2 = (pPriv->src_x + srcOffsetX2) & ~1;
|
|
sy2 = (pPriv->src_y + srcOffsetY2);
|
|
overlay.PSY2 = (pPriv->bufAddr[pPriv->currentBuf] + sx2*2 + sy2*srcPitch);
|
|
overlay.PSY2 += FBOFFSET;
|
|
overlay.PSY2 >>= pPriv->shiftValue;
|
|
}
|
|
#endif
|
|
break;
|
|
}
|
|
|
|
/* Some clipping checks */
|
|
#ifdef SISMERGED
|
|
if((!pSiS->MergedFB) || (overlay.DoFirst)) {
|
|
#endif
|
|
overlay.srcW = pPriv->src_w - (sx - pPriv->src_x);
|
|
overlay.srcH = pPriv->src_h - (sy - pPriv->src_y);
|
|
if( (pPriv->oldx1 != overlay.dstBox.x1) ||
|
|
(pPriv->oldx2 != overlay.dstBox.x2) ||
|
|
(pPriv->oldy1 != overlay.dstBox.y1) ||
|
|
(pPriv->oldy2 != overlay.dstBox.y2) ) {
|
|
pPriv->mustwait = 1;
|
|
pPriv->oldx1 = overlay.dstBox.x1; pPriv->oldx2 = overlay.dstBox.x2;
|
|
pPriv->oldy1 = overlay.dstBox.y1; pPriv->oldy2 = overlay.dstBox.y2;
|
|
}
|
|
#ifdef SISMERGED
|
|
}
|
|
if((pSiS->MergedFB) && (overlay.DoSecond)) {
|
|
overlay.srcW2 = pPriv->src_w - (sx2 - pPriv->src_x);
|
|
overlay.srcH2 = pPriv->src_h - (sy2 - pPriv->src_y);
|
|
if( (pPriv->oldx1_2 != overlay.dstBox2.x1) ||
|
|
(pPriv->oldx2_2 != overlay.dstBox2.x2) ||
|
|
(pPriv->oldy1_2 != overlay.dstBox2.y1) ||
|
|
(pPriv->oldy2_2 != overlay.dstBox2.y2) ) {
|
|
pPriv->mustwait = 1;
|
|
pPriv->oldx1_2 = overlay.dstBox2.x1; pPriv->oldx2_2 = overlay.dstBox2.x2;
|
|
pPriv->oldy1_2 = overlay.dstBox2.y1; pPriv->oldy2_2 = overlay.dstBox2.y2;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef SISMERGED
|
|
/* Disable an overlay if it is not to be displayed (but enabled currently) */
|
|
if((pSiS->MergedFB) && (pPriv->hasTwoOverlays)) {
|
|
if(!overlay.DoFirst) {
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0x05);
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x01);
|
|
temp = getvideoreg(pSiS,Index_VI_Control_Misc0);
|
|
if(temp & 0x02) {
|
|
watchdog = WATCHDOG_DELAY;
|
|
while((!vblank_active_CRT1(pSiS, pPriv)) && --watchdog);
|
|
watchdog = WATCHDOG_DELAY;
|
|
while(vblank_active_CRT1(pSiS, pPriv) && --watchdog);
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02);
|
|
}
|
|
} else if(!overlay.DoSecond) {
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, 0x01);
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x01);
|
|
temp = getvideoreg(pSiS,Index_VI_Control_Misc0);
|
|
if(temp & 0x02) {
|
|
watchdog = WATCHDOG_DELAY;
|
|
while((!vblank_active_CRT2(pSiS, pPriv)) && --watchdog);
|
|
watchdog = WATCHDOG_DELAY;
|
|
while(vblank_active_CRT2(pSiS, pPriv) && --watchdog);
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* Loop head */
|
|
/* Note: index can only be 1 for CRT2, ie overlay 1
|
|
* is only used for CRT2.
|
|
*/
|
|
if(pPriv->displayMode & DISPMODE_SINGLE2) {
|
|
if(pPriv->hasTwoOverlays) { /* We have 2 overlays: */
|
|
if(pPriv->dualHeadMode) {
|
|
/* Dual head: We use overlay 2 for CRT2 */
|
|
index = 1; iscrt2 = 1;
|
|
} else {
|
|
/* Single head: We use overlay 1 for CRT2 */
|
|
index = 0; iscrt2 = 1;
|
|
}
|
|
} else { /* We have 1 overlay */
|
|
/* We use that only overlay for CRT2 */
|
|
index = 0; iscrt2 = 1;
|
|
}
|
|
overlay.VBlankActiveFunc = vblank_active_CRT2;
|
|
#ifdef SISMERGED
|
|
if(!pPriv->hasTwoOverlays) {
|
|
if((pSiS->MergedFB) && (!overlay.DoSecond)) {
|
|
index = 0; iscrt2 = 0;
|
|
overlay.VBlankActiveFunc = vblank_active_CRT1;
|
|
pPriv->displayMode = DISPMODE_SINGLE1;
|
|
}
|
|
}
|
|
#endif
|
|
} else {
|
|
index = 0; iscrt2 = 0;
|
|
overlay.VBlankActiveFunc = vblank_active_CRT1;
|
|
#ifdef SISMERGED
|
|
if((pSiS->MergedFB) && (!overlay.DoFirst)) {
|
|
if(pPriv->hasTwoOverlays) index = 1;
|
|
iscrt2 = 1;
|
|
overlay.VBlankActiveFunc = vblank_active_CRT2;
|
|
if(!pPriv->hasTwoOverlays) {
|
|
pPriv->displayMode = DISPMODE_SINGLE2;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* set display mode SR06,32 (CRT1, CRT2 or mirror) */
|
|
set_disptype_regs(pScrn, pPriv);
|
|
|
|
/* set (not only calc) merge line buffer */
|
|
#ifdef SISMERGED
|
|
if(!pSiS->MergedFB) {
|
|
#endif
|
|
merge_line_buf(pSiS, pPriv, (overlay.srcW > pPriv->linebufMergeLimit), overlay.srcW,
|
|
pPriv->linebufMergeLimit);
|
|
#ifdef SISMERGED
|
|
} else {
|
|
Bool temp1 = FALSE, temp2 = FALSE;
|
|
if(overlay.DoFirst) {
|
|
if(overlay.srcW > pPriv->linebufMergeLimit) temp1 = TRUE;
|
|
}
|
|
if(overlay.DoSecond) {
|
|
if(overlay.srcW2 > pPriv->linebufMergeLimit) temp2 = TRUE;
|
|
}
|
|
merge_line_buf_mfb(pSiS, pPriv, temp1, temp2, overlay.srcW, overlay.srcW2,
|
|
pPriv->linebufMergeLimit);
|
|
}
|
|
#endif
|
|
|
|
/* calculate (not set!) line buffer length */
|
|
#ifdef SISMERGED
|
|
if((!pSiS->MergedFB) || (overlay.DoFirst))
|
|
#endif
|
|
calc_line_buf_size_1(&overlay, pPriv);
|
|
#ifdef SISMERGED
|
|
if((pSiS->MergedFB) && (overlay.DoSecond))
|
|
calc_line_buf_size_2(&overlay, pPriv);
|
|
#endif
|
|
|
|
if(pPriv->dualHeadMode) {
|
|
#ifdef SISDUALHEAD
|
|
if(!pSiS->SecondHead) {
|
|
if(pPriv->updatetvxpos) {
|
|
SiS_SetTVxposoffset(pScrn, pPriv->tvxpos);
|
|
pPriv->updatetvxpos = FALSE;
|
|
}
|
|
if(pPriv->updatetvypos) {
|
|
SiS_SetTVyposoffset(pScrn, pPriv->tvypos);
|
|
pPriv->updatetvypos = FALSE;
|
|
}
|
|
}
|
|
#endif
|
|
} else {
|
|
if(pPriv->updatetvxpos) {
|
|
SiS_SetTVxposoffset(pScrn, pPriv->tvxpos);
|
|
pPriv->updatetvxpos = FALSE;
|
|
}
|
|
if(pPriv->updatetvypos) {
|
|
SiS_SetTVyposoffset(pScrn, pPriv->tvypos);
|
|
pPriv->updatetvypos = FALSE;
|
|
}
|
|
}
|
|
|
|
#if 0 /* Clearing this does not seem to be required */
|
|
/* and might even be dangerous. */
|
|
if(pSiS->VGAEngine == SIS_315_VGA) {
|
|
watchdog = WATCHDOG_DELAY;
|
|
while(overlay.VBlankActiveFunc(pSiS, pPriv) && --watchdog);
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc3, 0x00, 0x03);
|
|
}
|
|
#endif
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc3, 0x03, 0x03);
|
|
|
|
/* Do the following in a loop for CRT1 and CRT2 ----------------- */
|
|
MIRROR:
|
|
|
|
/* calculate scale factor */
|
|
#ifdef SISMERGED
|
|
if(pSiS->MergedFB && iscrt2)
|
|
calc_scale_factor_2(&overlay, pScrn, pPriv, index, iscrt2);
|
|
else
|
|
#endif
|
|
calc_scale_factor(&overlay, pScrn, pPriv, index, iscrt2);
|
|
|
|
/* Select overlay 0 (used for CRT1/or CRT2) or overlay 1 (used for CRT2 only) */
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc2, index, 0x01);
|
|
|
|
/* set format (before color and chroma keys) */
|
|
set_format(pSiS, &overlay);
|
|
|
|
/* set color key */
|
|
set_colorkey(pSiS, pPriv->colorKey);
|
|
|
|
if(pPriv->usechromakey) {
|
|
/* Select chroma key format (300 series only) */
|
|
if(pSiS->VGAEngine == SIS_300_VGA) {
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc0,
|
|
(pPriv->yuvchromakey ? 0x40 : 0x00), 0x40);
|
|
}
|
|
set_chromakey(pSiS, pPriv->chromamin, pPriv->chromamax);
|
|
}
|
|
|
|
/* set brightness, contrast, hue, saturation */
|
|
set_brightness(pSiS, pPriv->brightness);
|
|
set_contrast(pSiS, pPriv->contrast);
|
|
if(pSiS->VGAEngine == SIS_315_VGA) {
|
|
set_hue(pSiS, pPriv->hue);
|
|
set_saturation(pSiS, pPriv->saturation);
|
|
}
|
|
|
|
/* enable/disable graphics display around overlay
|
|
* (Since disabled overlays don't get treated in this
|
|
* loop, we omit respective checks here)
|
|
*/
|
|
if(!iscrt2) {
|
|
set_disablegfx(pSiS, pPriv->disablegfx, &overlay);
|
|
} else if(!pSiS->hasTwoOverlays) {
|
|
set_disablegfx(pSiS, FALSE, &overlay);
|
|
}
|
|
set_disablegfxlr(pSiS, pPriv->disablegfxlr, &overlay);
|
|
|
|
#ifdef SIS_CP
|
|
SIS_CP_VIDEO_SET_CP
|
|
#endif
|
|
|
|
/* set remaining overlay parameters */
|
|
set_overlay(pSiS, &overlay, pPriv, index, iscrt2);
|
|
|
|
/* enable overlay */
|
|
setvideoregmask (pSiS, Index_VI_Control_Misc0, 0x02, 0x02);
|
|
|
|
/* loop foot */
|
|
if(pPriv->displayMode & DISPMODE_MIRROR &&
|
|
index == 0 &&
|
|
pPriv->hasTwoOverlays) {
|
|
#ifdef SISMERGED
|
|
if((!pSiS->MergedFB) || overlay.DoSecond) {
|
|
#endif
|
|
index = 1; iscrt2 = 1;
|
|
overlay.VBlankActiveFunc = vblank_active_CRT2;
|
|
goto MIRROR;
|
|
#ifdef SISMERGED
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* Now for the trigger: This is a bad hack to work-around
|
|
* an obvious hardware bug: Overlay 1 (which is ONLY used
|
|
* for CRT2 in this driver) does not always update its
|
|
* window position and some other stuff. Earlier, this was
|
|
* solved be disabling the overlay, but this took forever
|
|
* and was ugly on the screen.
|
|
* Now: We write 0x03 to 0x74 from the beginning. This is
|
|
* meant as a "lock" - the driver is supposed to write 0
|
|
* to this register, bit 0 for overlay 0, bit 1 for over-
|
|
* lay 1, then change buffer addresses, pitches, window
|
|
* position, scaler registers, format, etc., then write
|
|
* 1 to 0x74. The hardware then reads the registers into
|
|
* its internal engine and clears these bits.
|
|
* All this works for overlay 0, but not 1. Overlay 1
|
|
* has assumingly the following restrictions:
|
|
* - New data written to the registers is only read
|
|
* correctly by the engine if the registers are written
|
|
* when the current scanline is beyond the current
|
|
* overlay position and below the maximum visible
|
|
* scanline (vertical screen resolution)
|
|
* - If a vertical retrace occures during writing the
|
|
* registers, the registers written BEFORE this re-
|
|
* trace happened, are not being read into the
|
|
* engine if the trigger is set after the retrace.
|
|
* Therefore: We write the overlay registers above in
|
|
* set_overlay only if the scanline matches, and save
|
|
* the then current scanline. If this scanline is higher
|
|
* than the now current scanline, we assume a retrace,
|
|
* wait for the scanline to match the criteria above again,
|
|
* and rewrite all relevant registers.
|
|
* I have no idea if this is meant that way, but after
|
|
* fiddling three entire days with this crap, I found this
|
|
* to be the only solution.
|
|
*/
|
|
if(pSiS->VGAEngine == SIS_315_VGA) {
|
|
if((pPriv->mustwait) && index) {
|
|
watchdog = get_scanline_CRT2(pSiS, pPriv);
|
|
if(watchdog <= overlay.oldLine) {
|
|
int i, mytop = overlay.oldtop;
|
|
int screenHeight = overlay.SCREENheight;
|
|
#ifdef SISMERGED
|
|
if(pSiS->MergedFB) {
|
|
screenHeight = overlay.SCREENheight2;
|
|
}
|
|
#endif
|
|
if(mytop < screenHeight - 2) {
|
|
do {
|
|
watchdog = get_scanline_CRT2(pSiS, pPriv);
|
|
} while((watchdog <= mytop) || (watchdog >= screenHeight));
|
|
}
|
|
for(i=0x02; i<=0x12; i++) {
|
|
setvideoreg(pSiS, i, getvideoreg(pSiS, i));
|
|
}
|
|
for(i=0x18; i<=0x1c; i++) {
|
|
setvideoreg(pSiS, i, getvideoreg(pSiS, i));
|
|
}
|
|
for(i=0x2c; i<=0x2e; i++) {
|
|
setvideoreg(pSiS, i, getvideoreg(pSiS, i));
|
|
}
|
|
for(i=0x6b; i<=0x6f; i++) {
|
|
setvideoreg(pSiS, i, getvideoreg(pSiS, i));
|
|
}
|
|
}
|
|
}
|
|
/* Trigger register copy for 315/330 series */
|
|
setvideoregmask(pSiS, Index_VI_Control_Misc3, 0x03, 0x03);
|
|
}
|
|
|
|
pPriv->mustwait = 0;
|
|
pPriv->overlayStatus = TRUE;
|
|
}
|
|
|
|
/*********************************
|
|
* Memory management *
|
|
*********************************/
|
|
|
|
#ifdef SIS_USE_EXA
|
|
static void
|
|
SiSDestroyArea(ScreenPtr pScreen, ExaOffscreenArea *area)
|
|
{
|
|
void **handle = (void *)area->privData;
|
|
*handle = NULL;
|
|
}
|
|
#endif
|
|
|
|
unsigned int
|
|
SISAllocateFBMemory(
|
|
ScrnInfoPtr pScrn,
|
|
void **handle,
|
|
int bytesize
|
|
){
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
|
|
|
|
#ifdef SIS_USE_XAA
|
|
if(!pSiS->useEXA) {
|
|
FBLinearPtr linear = (FBLinearPtr)(*handle);
|
|
FBLinearPtr new_linear;
|
|
int depth = pSiS->CurrentLayout.bitsPerPixel >> 3;
|
|
int size = ((bytesize + depth - 1) / depth);
|
|
|
|
if(linear) {
|
|
if(linear->size >= size) {
|
|
return (unsigned int)(linear->offset * depth);
|
|
}
|
|
|
|
if(xf86ResizeOffscreenLinear(linear, size)) {
|
|
return (unsigned int)(linear->offset * depth);
|
|
}
|
|
|
|
xf86FreeOffscreenLinear(linear);
|
|
*handle = NULL;
|
|
}
|
|
|
|
new_linear = xf86AllocateOffscreenLinear(pScreen, size, 8, NULL, NULL, NULL);
|
|
|
|
if(!new_linear) {
|
|
int max_size;
|
|
|
|
xf86QueryLargestOffscreenLinear(pScreen, &max_size, 8, PRIORITY_EXTREME);
|
|
|
|
if(max_size < size)
|
|
return 0;
|
|
|
|
xf86PurgeUnlockedOffscreenAreas(pScreen);
|
|
new_linear = xf86AllocateOffscreenLinear(pScreen, size, 8, NULL, NULL, NULL);
|
|
}
|
|
if(!new_linear) {
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
|
"Xv: Failed to allocate %d pixels of linear video memory\n", size);
|
|
return 0;
|
|
} else {
|
|
*handle = (void *)new_linear;
|
|
return (unsigned int)(new_linear->offset * depth);
|
|
}
|
|
}
|
|
#endif
|
|
#ifdef SIS_USE_EXA
|
|
if(pSiS->useEXA && !pSiS->NoAccel) {
|
|
ExaOffscreenArea *area = (ExaOffscreenArea *)(*handle);
|
|
|
|
if(area) {
|
|
if(area->size >= bytesize) return (unsigned int)(area->offset);
|
|
|
|
exaOffscreenFree(pScreen, area);
|
|
*handle = NULL;
|
|
}
|
|
|
|
if(!(area = exaOffscreenAlloc(pScreen, bytesize, 8, TRUE, SiSDestroyArea, (pointer)handle))) {
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
|
"Xv: Failed to allocate %d bytes of video memory\n", bytesize);
|
|
return 0;
|
|
} else {
|
|
*handle = (void *)area;
|
|
return (unsigned int)(area->offset);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
SISFreeFBMemory(ScrnInfoPtr pScrn, void **handle)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
#ifdef SIS_USE_EXA
|
|
ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
|
|
#endif
|
|
|
|
#ifdef SIS_USE_XAA
|
|
if(!pSiS->useEXA) {
|
|
if(*handle) {
|
|
xf86FreeOffscreenLinear((FBLinearPtr)(*handle));
|
|
}
|
|
}
|
|
#endif
|
|
#ifdef SIS_USE_EXA
|
|
if(pSiS->useEXA && !pSiS->NoAccel) {
|
|
if(*handle) {
|
|
exaOffscreenFree(pScreen, (ExaOffscreenArea *)(*handle));
|
|
}
|
|
}
|
|
#endif
|
|
*handle = NULL;
|
|
}
|
|
|
|
/*********************************
|
|
* StopVideo() *
|
|
*********************************/
|
|
|
|
static void
|
|
SISStopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown)
|
|
{
|
|
SISPortPrivPtr pPriv = (SISPortPrivPtr)data;
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
|
|
if(pPriv->grabbedByV4L) return;
|
|
|
|
REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
|
|
|
|
if(shutdown) {
|
|
if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
|
|
close_overlay(pSiS, pPriv);
|
|
pPriv->mustwait = 1;
|
|
}
|
|
SISFreeFBMemory(pScrn, &pPriv->handle);
|
|
pPriv->videoStatus = 0;
|
|
} else {
|
|
if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
|
|
UpdateCurrentTime();
|
|
pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
|
|
pPriv->videoStatus = OFF_TIMER | CLIENT_VIDEO_ON;
|
|
pSiS->VideoTimerCallback = SISVideoTimerCallback;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*********************************
|
|
* PutImage() *
|
|
*********************************/
|
|
|
|
static int
|
|
SISPutImage(
|
|
ScrnInfoPtr pScrn,
|
|
short src_x, short src_y,
|
|
short drw_x, short drw_y,
|
|
short src_w, short src_h,
|
|
short drw_w, short drw_h,
|
|
int id, UChar *buf,
|
|
short width, short height,
|
|
Bool sync,
|
|
RegionPtr clipBoxes, pointer data,
|
|
DrawablePtr pDraw
|
|
){
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
SISPortPrivPtr pPriv = (SISPortPrivPtr)data;
|
|
#ifdef SIS_USE_XAA
|
|
XAAInfoRecPtr pXAA = pSiS->AccelInfoPtr;
|
|
int depth = pSiS->CurrentLayout.bitsPerPixel >> 3;
|
|
int myreds[] = { 0x000000ff, 0x0000f800, 0, 0x00ff0000 };
|
|
#endif
|
|
int totalSize = 0;
|
|
#ifdef SISDEINT
|
|
Bool deintfm = (pPriv->deinterlacemethod > 1) ? TRUE : FALSE;
|
|
#endif
|
|
|
|
#if 0
|
|
xf86DrvMsg(0, X_INFO, "PutImage: src %dx%d-%dx%d, drw %dx%d-%dx%d, id %x, w %d h %d, buf %p\n",
|
|
src_x, src_y, src_w, src_h, drw_x, drw_y, drw_w, drw_h, id, width, height, buf);
|
|
#endif
|
|
|
|
if(pPriv->grabbedByV4L) return Success;
|
|
|
|
pPriv->drw_x = drw_x;
|
|
pPriv->drw_y = drw_y;
|
|
pPriv->drw_w = drw_w;
|
|
pPriv->drw_h = drw_h;
|
|
pPriv->src_x = src_x;
|
|
pPriv->src_y = src_y;
|
|
pPriv->src_w = src_w;
|
|
pPriv->src_h = src_h;
|
|
pPriv->id = id;
|
|
pPriv->height = height;
|
|
|
|
/* Pixel formats:
|
|
1. YU12: 3 planes: H V
|
|
Y sample period 1 1 (8 bit per pixel)
|
|
V sample period 2 2 (8 bit per pixel, subsampled)
|
|
U sample period 2 2 (8 bit per pixel, subsampled)
|
|
|
|
Y plane is fully sampled (width*height), U and V planes
|
|
are sampled in 2x2 blocks, hence a group of 4 pixels requires
|
|
4 + 1 + 1 = 6 bytes. The data is planar, ie in single planes
|
|
for Y, U and V.
|
|
2. UYVY: 3 planes: H V
|
|
Y sample period 1 1 (8 bit per pixel)
|
|
V sample period 2 1 (8 bit per pixel, subsampled)
|
|
U sample period 2 1 (8 bit per pixel, subsampled)
|
|
Y plane is fully sampled (width*height), U and V planes
|
|
are sampled in 2x1 blocks, hence a group of 4 pixels requires
|
|
4 + 2 + 2 = 8 bytes. The data is bit packed, there are no separate
|
|
Y, U or V planes.
|
|
Bit order: U0 Y0 V0 Y1 U2 Y2 V2 Y3 ...
|
|
3. I420: Like YU12, but planes U and V are in reverse order.
|
|
4. YUY2: Like UYVY, but order is
|
|
Y0 U0 Y1 V0 Y2 U2 Y3 V2 ...
|
|
5. YVYU: Like YUY2, but order is
|
|
Y0 V0 Y1 U0 Y2 V2 Y3 U2 ...
|
|
6. NV12, NV21: 2 planes H V
|
|
Y sample period 1 1 (8 bit per pixel)
|
|
V sample period 2 1 (8 bit per pixel, subsampled)
|
|
U sample period 2 1 (8 bit per pixel, subsampled)
|
|
Y plane is fully samples (width*height), U and V planes are
|
|
interleaved in memory (one byte U, one byte V for NV12, NV21
|
|
other way round) and sampled in 2x1 blocks. Otherwise such
|
|
as all other planar formats.
|
|
*/
|
|
|
|
switch(id){
|
|
case PIXEL_FMT_YV12:
|
|
case PIXEL_FMT_I420:
|
|
case PIXEL_FMT_NV12:
|
|
case PIXEL_FMT_NV21:
|
|
pPriv->srcPitch = (width + 7) & ~7;
|
|
/* Size = width * height * 3 / 2 */
|
|
totalSize = (pPriv->srcPitch * height * 3) >> 1; /* Verified */
|
|
break;
|
|
case PIXEL_FMT_YUY2:
|
|
case PIXEL_FMT_UYVY:
|
|
case PIXEL_FMT_YVYU:
|
|
case PIXEL_FMT_RGB6:
|
|
case PIXEL_FMT_RGB5:
|
|
default:
|
|
pPriv->srcPitch = ((width << 1) + 3) & ~3; /* Verified */
|
|
/* Size = width * 2 * height */
|
|
totalSize = pPriv->srcPitch * height;
|
|
}
|
|
|
|
/* make it a multiple of 16 to simplify to copy loop */
|
|
totalSize += 15;
|
|
totalSize &= ~15; /* in bytes */
|
|
|
|
/* allocate memory (we do doublebuffering) - size is in bytes */
|
|
if(!(pPriv->bufAddr[0] = SISAllocateFBMemory(pScrn, &pPriv->handle, totalSize << 1)))
|
|
return BadAlloc;
|
|
|
|
#ifdef SISDEINT
|
|
if(deintfm) {
|
|
pPriv->bufAddr[1] = pPriv->bufAddr[0] + pPriv->srcPitch;
|
|
|
|
{
|
|
CARD8 *src = (CARD8 *)buf;
|
|
CARD8 *dest = (CARD8 *)(pSiS->FbBase + pPriv->bufAddr[pPriv->currentBuf]);
|
|
int i = height;
|
|
while(i--) {
|
|
SiSMemCopyToVideoRam(pSiS, dest, src, pPriv->srcPitch);
|
|
src += pPriv->srcPitch;
|
|
dest += (pPriv->srcPitch << 1);
|
|
}
|
|
}
|
|
|
|
} else {
|
|
#endif
|
|
pPriv->bufAddr[1] = pPriv->bufAddr[0] + totalSize;
|
|
|
|
/* copy data */
|
|
if((pSiS->XvUseMemcpy) || (totalSize < 16)) {
|
|
SiSMemCopyToVideoRam(pSiS, pSiS->FbBase + pPriv->bufAddr[pPriv->currentBuf], buf, totalSize);
|
|
} else {
|
|
ULong i;
|
|
CARD32 *src = (CARD32 *)buf;
|
|
CARD32 *dest = (CARD32 *)(pSiS->FbBase + pPriv->bufAddr[pPriv->currentBuf]);
|
|
for(i = 0; i < (totalSize/16); i++) {
|
|
*dest++ = *src++;
|
|
*dest++ = *src++;
|
|
*dest++ = *src++;
|
|
*dest++ = *src++;
|
|
}
|
|
}
|
|
#ifdef SISDEINT
|
|
}
|
|
#endif
|
|
|
|
SISDisplayVideo(pScrn, pPriv);
|
|
|
|
/* update cliplist */
|
|
if(pPriv->autopaintColorKey &&
|
|
(pPriv->grabbedByV4L ||
|
|
#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,3,99,3,0)
|
|
(!RegionsEqual(&pPriv->clip, clipBoxes)) ||
|
|
#else
|
|
(!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) ||
|
|
#endif
|
|
(pPriv->PrevOverlay != pPriv->NoOverlay))) {
|
|
/* We always paint the colorkey for V4L */
|
|
if(!pPriv->grabbedByV4L) {
|
|
REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
|
|
}
|
|
/* draw these */
|
|
pPriv->PrevOverlay = pPriv->NoOverlay;
|
|
#ifdef SIS_USE_XAA
|
|
if((pPriv->NoOverlay) && pXAA && pXAA->FillMono8x8PatternRects) {
|
|
(*pXAA->FillMono8x8PatternRects)(pScrn, myreds[depth-1],
|
|
0x000000, GXcopy, ~0,
|
|
REGION_NUM_RECTS(clipBoxes),
|
|
REGION_RECTS(clipBoxes),
|
|
0x00422418, 0x18244200, 0, 0);
|
|
} else {
|
|
#endif
|
|
if(!pSiS->disablecolorkeycurrent) {
|
|
#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,1,99,1,0)
|
|
(*pXAA->FillSolidRects)(pScrn, pPriv->colorKey, GXcopy, ~0,
|
|
REGION_NUM_RECTS(clipBoxes),
|
|
REGION_RECTS(clipBoxes));
|
|
#else
|
|
xf86XVFillKeyHelper(pScrn->pScreen, (pPriv->NoOverlay) ? 0x00ff0000 : pPriv->colorKey, clipBoxes);
|
|
#endif
|
|
}
|
|
#ifdef SIS_USE_XAA
|
|
}
|
|
#endif
|
|
|
|
}
|
|
|
|
pPriv->currentBuf ^= 1;
|
|
|
|
pPriv->videoStatus = CLIENT_VIDEO_ON;
|
|
|
|
pSiS->VideoTimerCallback = SISVideoTimerCallback;
|
|
|
|
return Success;
|
|
}
|
|
|
|
/*********************************
|
|
* QueryImageAttributes() *
|
|
*********************************/
|
|
|
|
static int
|
|
SISQueryImageAttributes(
|
|
ScrnInfoPtr pScrn,
|
|
int id,
|
|
UShort *w, UShort *h,
|
|
int *pitches, int *offsets
|
|
){
|
|
int pitchY, pitchUV;
|
|
int size, sizeY, sizeUV;
|
|
|
|
if(*w < IMAGE_MIN_WIDTH) *w = IMAGE_MIN_WIDTH;
|
|
if(*h < IMAGE_MIN_HEIGHT) *h = IMAGE_MIN_HEIGHT;
|
|
|
|
if(*w > DummyEncoding.width) *w = DummyEncoding.width;
|
|
if(*h > DummyEncoding.height) *h = DummyEncoding.height;
|
|
|
|
switch(id) {
|
|
case PIXEL_FMT_YV12:
|
|
case PIXEL_FMT_I420:
|
|
*w = (*w + 7) & ~7;
|
|
*h = (*h + 1) & ~1;
|
|
pitchY = *w;
|
|
pitchUV = *w >> 1;
|
|
if(pitches) {
|
|
pitches[0] = pitchY;
|
|
pitches[1] = pitches[2] = pitchUV;
|
|
}
|
|
sizeY = pitchY * (*h);
|
|
sizeUV = pitchUV * ((*h) >> 1);
|
|
if(offsets) {
|
|
offsets[0] = 0;
|
|
offsets[1] = sizeY;
|
|
offsets[2] = sizeY + sizeUV;
|
|
}
|
|
size = sizeY + (sizeUV << 1);
|
|
break;
|
|
case PIXEL_FMT_NV12:
|
|
case PIXEL_FMT_NV21:
|
|
*w = (*w + 7) & ~7;
|
|
*h = (*h + 1) & ~1;
|
|
pitchY = *w;
|
|
pitchUV = *w;
|
|
if(pitches) {
|
|
pitches[0] = pitchY;
|
|
pitches[1] = pitchUV;
|
|
}
|
|
sizeY = pitchY * (*h);
|
|
sizeUV = pitchUV * ((*h) >> 1);
|
|
if(offsets) {
|
|
offsets[0] = 0;
|
|
offsets[1] = sizeY;
|
|
}
|
|
size = sizeY + (sizeUV << 1);
|
|
break;
|
|
case PIXEL_FMT_YUY2:
|
|
case PIXEL_FMT_UYVY:
|
|
case PIXEL_FMT_YVYU:
|
|
case PIXEL_FMT_RGB6:
|
|
case PIXEL_FMT_RGB5:
|
|
default:
|
|
*w = (*w + 1) & ~1;
|
|
pitchY = *w << 1;
|
|
if(pitches) pitches[0] = pitchY;
|
|
if(offsets) offsets[0] = 0;
|
|
size = pitchY * (*h);
|
|
break;
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
|
|
/*********************************
|
|
* OFFSCREEN SURFACES *
|
|
*********************************/
|
|
|
|
static int
|
|
SISAllocSurface (
|
|
ScrnInfoPtr pScrn,
|
|
int id,
|
|
UShort w,
|
|
UShort h,
|
|
XF86SurfacePtr surface
|
|
)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);
|
|
int size;
|
|
|
|
if((w < IMAGE_MIN_WIDTH) || (h < IMAGE_MIN_HEIGHT))
|
|
return BadValue;
|
|
|
|
if((w > DummyEncoding.width) || (h > DummyEncoding.height))
|
|
return BadValue;
|
|
|
|
if(pPriv->grabbedByV4L)
|
|
return BadAlloc;
|
|
|
|
w = (w + 1) & ~1;
|
|
pPriv->pitch = ((w << 1) + 63) & ~63; /* Only packed pixel modes supported */
|
|
size = h * pPriv->pitch;
|
|
if(!(pPriv->offset = SISAllocateFBMemory(pScrn, &pPriv->handle, size)))
|
|
return BadAlloc;
|
|
|
|
surface->width = w;
|
|
surface->height = h;
|
|
surface->pScrn = pScrn;
|
|
surface->id = id;
|
|
surface->pitches = &pPriv->pitch;
|
|
surface->offsets = &pPriv->offset;
|
|
surface->devPrivate.ptr = (pointer)pPriv;
|
|
|
|
close_overlay(pSiS, pPriv);
|
|
pPriv->videoStatus = 0;
|
|
REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
|
|
pSiS->VideoTimerCallback = NULL;
|
|
pPriv->grabbedByV4L = TRUE;
|
|
return Success;
|
|
}
|
|
|
|
static int
|
|
SISStopSurface (XF86SurfacePtr surface)
|
|
{
|
|
SISPortPrivPtr pPriv = (SISPortPrivPtr)(surface->devPrivate.ptr);
|
|
SISPtr pSiS = SISPTR(surface->pScrn);
|
|
|
|
if(pPriv->grabbedByV4L && pPriv->videoStatus) {
|
|
close_overlay(pSiS, pPriv);
|
|
pPriv->mustwait = 1;
|
|
pPriv->videoStatus = 0;
|
|
}
|
|
return Success;
|
|
}
|
|
|
|
static int
|
|
SISFreeSurface (XF86SurfacePtr surface)
|
|
{
|
|
SISPortPrivPtr pPriv = (SISPortPrivPtr)(surface->devPrivate.ptr);
|
|
|
|
if(pPriv->grabbedByV4L) {
|
|
SISStopSurface(surface);
|
|
SISFreeFBMemory(surface->pScrn, &pPriv->handle);
|
|
pPriv->grabbedByV4L = FALSE;
|
|
}
|
|
return Success;
|
|
}
|
|
|
|
static int
|
|
SISGetSurfaceAttribute (
|
|
ScrnInfoPtr pScrn,
|
|
Atom attribute,
|
|
INT32 *value
|
|
)
|
|
{
|
|
SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);
|
|
|
|
return SISGetPortAttribute(pScrn, attribute, value, (pointer)pPriv);
|
|
}
|
|
|
|
static int
|
|
SISSetSurfaceAttribute(
|
|
ScrnInfoPtr pScrn,
|
|
Atom attribute,
|
|
INT32 value
|
|
)
|
|
{
|
|
SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);;
|
|
|
|
return SISSetPortAttribute(pScrn, attribute, value, (pointer)pPriv);
|
|
}
|
|
|
|
static int
|
|
SISDisplaySurface (
|
|
XF86SurfacePtr surface,
|
|
short src_x, short src_y,
|
|
short drw_x, short drw_y,
|
|
short src_w, short src_h,
|
|
short drw_w, short drw_h,
|
|
RegionPtr clipBoxes
|
|
)
|
|
{
|
|
ScrnInfoPtr pScrn = surface->pScrn;
|
|
SISPortPrivPtr pPriv = (SISPortPrivPtr)(surface->devPrivate.ptr);
|
|
#ifdef SIS_USE_XAA
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
int myreds[] = { 0x000000ff, 0x0000f800, 0, 0x00ff0000 };
|
|
#endif
|
|
|
|
if(!pPriv->grabbedByV4L) return Success;
|
|
|
|
pPriv->drw_x = drw_x;
|
|
pPriv->drw_y = drw_y;
|
|
pPriv->drw_w = drw_w;
|
|
pPriv->drw_h = drw_h;
|
|
pPriv->src_x = src_x;
|
|
pPriv->src_y = src_y;
|
|
pPriv->src_w = src_w;
|
|
pPriv->src_h = src_h;
|
|
pPriv->id = surface->id;
|
|
pPriv->height = surface->height;
|
|
pPriv->bufAddr[0] = surface->offsets[0];
|
|
pPriv->currentBuf = 0;
|
|
pPriv->srcPitch = surface->pitches[0];
|
|
|
|
SISDisplayVideo(pScrn, pPriv);
|
|
|
|
if(pPriv->autopaintColorKey) {
|
|
#ifdef SIS_USE_XAA
|
|
XAAInfoRecPtr pXAA = pSiS->AccelInfoPtr;
|
|
|
|
if((pPriv->NoOverlay) && pXAA && pXAA->FillMono8x8PatternRects) {
|
|
(*pXAA->FillMono8x8PatternRects)(pScrn,
|
|
myreds[(pSiS->CurrentLayout.bitsPerPixel >> 3) - 1],
|
|
0x000000, GXcopy, ~0,
|
|
REGION_NUM_RECTS(clipBoxes),
|
|
REGION_RECTS(clipBoxes),
|
|
0x00422418, 0x18244200, 0, 0);
|
|
|
|
} else {
|
|
#endif
|
|
#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,1,99,1,0)
|
|
(*pXAA->FillSolidRects)(pScrn, pPriv->colorKey, GXcopy, ~0,
|
|
REGION_NUM_RECTS(clipBoxes),
|
|
REGION_RECTS(clipBoxes));
|
|
#else
|
|
xf86XVFillKeyHelper(pScrn->pScreen, (pPriv->NoOverlay) ? 0x00ff0000 : pPriv->colorKey, clipBoxes);
|
|
#endif
|
|
#ifdef SIS_USE_XAA
|
|
}
|
|
#endif
|
|
}
|
|
|
|
pPriv->videoStatus = CLIENT_VIDEO_ON;
|
|
|
|
return Success;
|
|
}
|
|
|
|
#define NUMOFFSCRIMAGES_300 4
|
|
#define NUMOFFSCRIMAGES_315 5
|
|
|
|
static XF86OffscreenImageRec SISOffscreenImages[NUMOFFSCRIMAGES_315] =
|
|
{
|
|
{
|
|
&SISImages[0], /* YUV2 */
|
|
VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
|
|
SISAllocSurface,
|
|
SISFreeSurface,
|
|
SISDisplaySurface,
|
|
SISStopSurface,
|
|
SISGetSurfaceAttribute,
|
|
SISSetSurfaceAttribute,
|
|
0, 0, /* Rest will be filled in */
|
|
0,
|
|
NULL
|
|
},
|
|
{
|
|
&SISImages[2], /* UYVY */
|
|
VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
|
|
SISAllocSurface,
|
|
SISFreeSurface,
|
|
SISDisplaySurface,
|
|
SISStopSurface,
|
|
SISGetSurfaceAttribute,
|
|
SISSetSurfaceAttribute,
|
|
0, 0, /* Rest will be filled in */
|
|
0,
|
|
NULL
|
|
}
|
|
,
|
|
{
|
|
&SISImages[4], /* RV15 */
|
|
VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
|
|
SISAllocSurface,
|
|
SISFreeSurface,
|
|
SISDisplaySurface,
|
|
SISStopSurface,
|
|
SISGetSurfaceAttribute,
|
|
SISSetSurfaceAttribute,
|
|
0, 0, /* Rest will be filled in */
|
|
0,
|
|
NULL
|
|
},
|
|
{
|
|
&SISImages[5], /* RV16 */
|
|
VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
|
|
SISAllocSurface,
|
|
SISFreeSurface,
|
|
SISDisplaySurface,
|
|
SISStopSurface,
|
|
SISGetSurfaceAttribute,
|
|
SISSetSurfaceAttribute,
|
|
0, 0, /* Rest will be filled in */
|
|
0,
|
|
NULL
|
|
},
|
|
{
|
|
&SISImages[6], /* YVYU */
|
|
VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
|
|
SISAllocSurface,
|
|
SISFreeSurface,
|
|
SISDisplaySurface,
|
|
SISStopSurface,
|
|
SISGetSurfaceAttribute,
|
|
SISSetSurfaceAttribute,
|
|
0, 0, /* Rest will be filled in */
|
|
0,
|
|
NULL
|
|
}
|
|
};
|
|
|
|
static void
|
|
SISInitOffscreenImages(ScreenPtr pScreen)
|
|
{
|
|
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
int i, num;
|
|
|
|
if(pSiS->VGAEngine == SIS_300_VGA) num = NUMOFFSCRIMAGES_300;
|
|
else num = NUMOFFSCRIMAGES_315;
|
|
|
|
for(i = 0; i < num; i++) {
|
|
SISOffscreenImages[i].max_width = DummyEncoding.width;
|
|
SISOffscreenImages[i].max_height = DummyEncoding.height;
|
|
if(pSiS->VGAEngine == SIS_300_VGA) {
|
|
SISOffscreenImages[i].attributes = &SISAttributes_300[0];
|
|
SISOffscreenImages[i].num_attributes = SiSCountAttributes(&SISAttributes_300[0]);
|
|
} else {
|
|
SISOffscreenImages[i].attributes = &SISAttributes_315[0];
|
|
SISOffscreenImages[i].num_attributes = SiSCountAttributes(&SISAttributes_315[0]);
|
|
if((pSiS->hasTwoOverlays) && (!(pSiS->SiS_SD2_Flags & SiS_SD2_SUPPORT760OO))) {
|
|
SISOffscreenImages[i].num_attributes--;
|
|
}
|
|
}
|
|
}
|
|
xf86XVRegisterOffscreenImages(pScreen, SISOffscreenImages, num);
|
|
}
|
|
|
|
/*****************************************************************/
|
|
/* BLIT ADAPTORS */
|
|
/*****************************************************************/
|
|
#ifdef INCL_YUV_BLIT_ADAPTOR
|
|
|
|
static void
|
|
SISSetPortDefaultsBlit(ScrnInfoPtr pScrn, SISBPortPrivPtr pPriv)
|
|
{
|
|
/* Default: Don't sync. */
|
|
pPriv->vsync = 0;
|
|
}
|
|
|
|
static void
|
|
SISResetVideoBlit(ScrnInfoPtr pScrn)
|
|
{
|
|
}
|
|
|
|
static XF86VideoAdaptorPtr
|
|
SISSetupBlitVideo(ScreenPtr pScreen)
|
|
{
|
|
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
XF86VideoAdaptorPtr adapt;
|
|
SISBPortPrivPtr pPriv;
|
|
int i;
|
|
|
|
#ifdef SIS_USE_XAA
|
|
if(!pSiS->useEXA) {
|
|
if(!pSiS->AccelInfoPtr) return NULL;
|
|
}
|
|
#endif
|
|
|
|
if(!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
|
|
(sizeof(DevUnion) * NUM_BLIT_PORTS) +
|
|
sizeof(SISBPortPrivRec)))) {
|
|
return NULL;
|
|
}
|
|
|
|
adapt->type = XvWindowMask | XvInputMask | XvImageMask;
|
|
adapt->flags = 0;
|
|
adapt->name = "SIS 315/330 series Video Blitter";
|
|
adapt->nEncodings = 1;
|
|
adapt->pEncodings = &DummyEncodingBlit;
|
|
adapt->nFormats = NUM_FORMATS;
|
|
adapt->pFormats = SISFormats;
|
|
adapt->nImages = NUM_IMAGES_BLIT;
|
|
adapt->pImages = SISImagesBlit;
|
|
adapt->pAttributes = SISAttributes_Blit;
|
|
adapt->nAttributes = NUM_ATTRIBUTES_BLIT;
|
|
adapt->nPorts = NUM_BLIT_PORTS;
|
|
adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
|
|
|
|
pSiS->blitPriv = (void *)(&adapt->pPortPrivates[NUM_BLIT_PORTS]);
|
|
pPriv = (SISBPortPrivPtr)(pSiS->blitPriv);
|
|
|
|
for(i = 0; i < NUM_BLIT_PORTS; i++) {
|
|
adapt->pPortPrivates[i].uval = (ULong)(i);
|
|
#if defined(REGION_NULL)
|
|
REGION_NULL(pScreen, &pPriv->blitClip[i]);
|
|
#else
|
|
REGION_INIT(pScreen, &pPriv->blitClip[i], NullBox, 0);
|
|
#endif
|
|
pPriv->videoStatus[i] = 0;
|
|
pPriv->currentBuf[i] = 0;
|
|
pPriv->handle[i] = NULL;
|
|
}
|
|
|
|
/* Scanline trigger not implemented by hardware! */
|
|
pPriv->VBlankTriggerCRT1 = 0; /* SCANLINE_TRIGGER_ENABLE | SCANLINE_TR_CRT1; */
|
|
pPriv->VBlankTriggerCRT2 = 0; /* SCANLINE_TRIGGER_ENABLE | SCANLINE_TR_CRT2; */
|
|
if(pSiS->ChipType >= SIS_330) {
|
|
pPriv->AccelCmd = YUVRGB_BLIT_330;
|
|
} else {
|
|
pPriv->AccelCmd = YUVRGB_BLIT_325;
|
|
}
|
|
|
|
adapt->PutVideo = NULL;
|
|
adapt->PutStill = NULL;
|
|
adapt->GetVideo = NULL;
|
|
adapt->GetStill = NULL;
|
|
adapt->StopVideo = (StopVideoFuncPtr)SISStopVideoBlit;
|
|
adapt->SetPortAttribute = (SetPortAttributeFuncPtr)SISSetPortAttributeBlit;
|
|
adapt->GetPortAttribute = (GetPortAttributeFuncPtr)SISGetPortAttributeBlit;
|
|
adapt->QueryBestSize = (QueryBestSizeFuncPtr)SISQueryBestSizeBlit;
|
|
adapt->PutImage = (PutImageFuncPtr)SISPutImageBlit;
|
|
adapt->QueryImageAttributes = SISQueryImageAttributesBlit;
|
|
|
|
pSiS->blitadaptor = adapt;
|
|
|
|
pSiS->xvVSync = MAKE_ATOM(sisxvvsync);
|
|
pSiS->xvSetDefaults = MAKE_ATOM(sisxvsetdefaults);
|
|
|
|
SISResetVideoBlit(pScrn);
|
|
|
|
/* Reset the properties to their defaults */
|
|
SISSetPortDefaultsBlit(pScrn, pPriv);
|
|
|
|
return adapt;
|
|
}
|
|
|
|
static int
|
|
SISGetPortAttributeBlit(ScrnInfoPtr pScrn, Atom attribute,
|
|
INT32 *value, ULong index)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
SISBPortPrivPtr pPriv = (SISBPortPrivPtr)(pSiS->blitPriv);
|
|
|
|
if(attribute == pSiS->xvVSync) {
|
|
*value = pPriv->vsync;
|
|
} else return BadMatch;
|
|
return Success;
|
|
}
|
|
|
|
static int
|
|
SISSetPortAttributeBlit(ScrnInfoPtr pScrn, Atom attribute,
|
|
INT32 value, ULong index)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
SISBPortPrivPtr pPriv = (SISBPortPrivPtr)(pSiS->blitPriv);
|
|
|
|
if(attribute == pSiS->xvVSync) {
|
|
if((value < 0) || (value > 1)) return BadValue;
|
|
pPriv->vsync = value;
|
|
} else if(attribute == pSiS->xvSetDefaults) {
|
|
SISSetPortDefaultsBlit(pScrn, pPriv);
|
|
} else return BadMatch;
|
|
return Success;
|
|
}
|
|
|
|
static void
|
|
SISStopVideoBlit(ScrnInfoPtr pScrn, ULong index, Bool shutdown)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
SISBPortPrivPtr pPriv = (SISBPortPrivPtr)(pSiS->blitPriv);
|
|
|
|
/* This shouldn't be called for blitter adaptors due to
|
|
* adapt->flags but we provide it anyway.
|
|
*/
|
|
|
|
if(index > NUM_BLIT_PORTS) return;
|
|
|
|
REGION_EMPTY(pScrn->pScreen, &pPriv->blitClip[index]);
|
|
|
|
if(shutdown) {
|
|
(*pSiS->SyncAccel)(pScrn);
|
|
pPriv->videoStatus[index] = 0;
|
|
SISFreeFBMemory(pScrn, &pPriv->handle[(int)index]);
|
|
}
|
|
}
|
|
|
|
static int
|
|
SISPutImageBlit(
|
|
ScrnInfoPtr pScrn,
|
|
short src_x, short src_y,
|
|
short drw_x, short drw_y,
|
|
short src_w, short src_h,
|
|
short drw_w, short drw_h,
|
|
int id, UChar *buf,
|
|
short width, short height,
|
|
Bool sync,
|
|
RegionPtr clipBoxes, ULong index,
|
|
DrawablePtr pDraw
|
|
){
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
SISBPortPrivPtr pPriv = (SISBPortPrivPtr)(pSiS->blitPriv);
|
|
#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,1,99,1,0)
|
|
XAAInfoRecPtr pXAA = pSiS->AccelInfoPtr;
|
|
#endif
|
|
BoxPtr pbox = REGION_RECTS(clipBoxes);
|
|
int nbox = REGION_NUM_RECTS(clipBoxes);
|
|
CARD32 dstbase = 0, offsety, offsetuv, temp;
|
|
int totalSize, bytesize=0, h, w, wb, srcPitch;
|
|
int xoffset = 0, yoffset = 0, left, right, top, bottom;
|
|
UChar *ybases, *ubases = NULL, *vbases = NULL, *myubases, *myvbases;
|
|
UChar *ybased, *uvbased, packed;
|
|
CARD16 *myuvbased;
|
|
SiS_Packet12_YUV MyPacket;
|
|
Bool first;
|
|
|
|
if(index > NUM_BLIT_PORTS) return BadMatch;
|
|
|
|
if(!height || !width) return Success;
|
|
|
|
switch(id) {
|
|
case PIXEL_FMT_YV12:
|
|
case PIXEL_FMT_I420:
|
|
case PIXEL_FMT_NV12:
|
|
case PIXEL_FMT_NV21:
|
|
srcPitch = (width + 7) & ~7; /* Should come this way anyway */
|
|
bytesize = srcPitch * height;
|
|
totalSize = (bytesize * 3) >> 1;
|
|
break;
|
|
case PIXEL_FMT_YUY2:
|
|
case PIXEL_FMT_UYVY:
|
|
case PIXEL_FMT_YVYU:
|
|
srcPitch = ((width << 1) + 3) & ~3;
|
|
/* Size = width * 2 * height */
|
|
totalSize = srcPitch * height;
|
|
bytesize = 0;
|
|
break;
|
|
default:
|
|
return BadMatch;
|
|
}
|
|
|
|
/* allocate memory (we do doublebuffering) */
|
|
if(!(pPriv->bufAddr[index][0] = SISAllocateFBMemory(pScrn, &pPriv->handle[index], totalSize << 1)))
|
|
return BadAlloc;
|
|
|
|
pPriv->bufAddr[index][1] = pPriv->bufAddr[index][0] + totalSize;
|
|
|
|
if(drw_w > width) {
|
|
xoffset = (drw_w - width) >> 1;
|
|
}
|
|
if(drw_h > (height & ~1)) {
|
|
yoffset = (drw_h - height) >> 1;
|
|
}
|
|
|
|
if(xoffset || yoffset) {
|
|
#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,3,99,3,0)
|
|
if(!RegionsEqual(&pPriv->blitClip[index], clipBoxes)) {
|
|
#else
|
|
if(!REGION_EQUAL(pScrn->pScreen, &pPriv->blitClip[index], clipBoxes)) {
|
|
#endif
|
|
#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,1,99,1,0)
|
|
(*pXAA->FillSolidRects)(pScrn, 0x00000000, GXcopy, ~0,
|
|
REGION_NUM_RECTS(clipBoxes),
|
|
REGION_RECTS(clipBoxes));
|
|
#else
|
|
xf86XVFillKeyHelper(pScrn->pScreen, 0x00000000, clipBoxes);
|
|
#endif
|
|
REGION_COPY(pScrn->pScreen, &pPriv->blitClip[index], clipBoxes);
|
|
}
|
|
}
|
|
|
|
memset(&MyPacket, 0, sizeof(MyPacket));
|
|
|
|
ybased = pSiS->FbBase + pPriv->bufAddr[index][pPriv->currentBuf[index]];
|
|
uvbased = pSiS->FbBase + pPriv->bufAddr[index][pPriv->currentBuf[index]] + bytesize;
|
|
|
|
ybases = buf;
|
|
packed = 0;
|
|
|
|
switch(id) {
|
|
case PIXEL_FMT_YV12:
|
|
vbases = buf + bytesize;
|
|
ubases = buf + bytesize*5/4;
|
|
break;
|
|
case PIXEL_FMT_I420:
|
|
ubases = buf + bytesize;
|
|
vbases = buf + bytesize*5/4;
|
|
break;
|
|
case PIXEL_FMT_NV12:
|
|
MyPacket.P12_Command = YUV_FORMAT_NV12;
|
|
break;
|
|
case PIXEL_FMT_NV21:
|
|
MyPacket.P12_Command = YUV_FORMAT_NV21;
|
|
break;
|
|
case PIXEL_FMT_YUY2:
|
|
MyPacket.P12_Command = YUV_FORMAT_YUY2;
|
|
packed = 1;
|
|
break;
|
|
case PIXEL_FMT_UYVY:
|
|
MyPacket.P12_Command = YUV_FORMAT_UYVY;
|
|
packed = 1;
|
|
break;
|
|
case PIXEL_FMT_YVYU:
|
|
MyPacket.P12_Command = YUV_FORMAT_YVYU;
|
|
packed = 1;
|
|
break;
|
|
default:
|
|
return BadMatch;
|
|
}
|
|
|
|
switch(id) {
|
|
case PIXEL_FMT_YV12:
|
|
case PIXEL_FMT_I420:
|
|
MyPacket.P12_Command = YUV_FORMAT_NV12;
|
|
/* Copy y plane */
|
|
SiSMemCopyToVideoRam(pSiS, ybased, ybases, bytesize);
|
|
/* Copy u/v planes */
|
|
wb = srcPitch >> 1;
|
|
h = height >> 1;
|
|
while(h--) {
|
|
myuvbased = (CARD16*)uvbased;
|
|
myubases = ubases;
|
|
myvbases = vbases;
|
|
w = wb;
|
|
while(w--) {
|
|
#if X_BYTE_ORDER == X_BIG_ENDIAN
|
|
temp = (*myubases++) << 8;
|
|
temp |= (*myvbases++);
|
|
#else
|
|
temp = (*myvbases++) << 8;
|
|
temp |= (*myubases++);
|
|
#endif
|
|
*myuvbased++ = temp;
|
|
}
|
|
uvbased += srcPitch;
|
|
ubases += wb;
|
|
vbases += wb;
|
|
}
|
|
break;
|
|
default:
|
|
SiSMemCopyToVideoRam(pSiS, ybased, ybases, totalSize);
|
|
}
|
|
|
|
dstbase += FBOFFSET;
|
|
|
|
MyPacket.P12_Header0 = SIS_PACKET12_HEADER0;
|
|
MyPacket.P12_Header1 = SIS_PACKET12_HEADER1;
|
|
MyPacket.P12_Null1 = SIS_NIL_CMD;
|
|
MyPacket.P12_Null2 = SIS_NIL_CMD;
|
|
MyPacket.P12_YPitch = MyPacket.P12_UVPitch = srcPitch;
|
|
MyPacket.P12_DstAddr = dstbase;
|
|
MyPacket.P12_DstPitch = pSiS->scrnOffset;
|
|
MyPacket.P12_DstHeight = 0x0fff;
|
|
|
|
MyPacket.P12_Command |= pPriv->AccelCmd |
|
|
SRCVIDEO |
|
|
PATFG |
|
|
pSiS->SiS310_AccelDepth |
|
|
YUV_CMD_YUV |
|
|
DSTVIDEO;
|
|
|
|
|
|
#if 0 /* Not implemented by hardware! */
|
|
if(pPriv->vsync) {
|
|
#ifdef SISMERGED
|
|
if(!pSiS->MergedFB) {
|
|
#endif
|
|
#ifdef SISDUALHEAD
|
|
if(pSiS->DualHeadMode) {
|
|
if(pSiS->SecondHead) {
|
|
MyPacket.P12_Command |= pPriv->VBlankTriggerCRT1;
|
|
} else {
|
|
MyPacket.P12_Command |= pPriv->VBlankTriggerCRT2;
|
|
}
|
|
} else {
|
|
#endif
|
|
Bool IsSlaveMode = SiSBridgeIsInSlaveMode(pScrn);
|
|
if((pSiS->VBFlags & DISPTYPE_DISP2) && !IsSlaveMode)
|
|
MyPacket.P12_Command |= pPriv->VBlankTriggerCRT2;
|
|
else if((pSiS->VBFlags & DISPTYPE_DISP1) || IsSlaveMode)
|
|
MyPacket.P12_Command |= pPriv->VBlankTriggerCRT1;
|
|
#ifdef SISDUALHEAD
|
|
}
|
|
#endif
|
|
#ifdef SISMERGED
|
|
}
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
first = TRUE;
|
|
while(nbox--) {
|
|
left = pbox->x1;
|
|
if(left >= drw_x + xoffset + width) goto mycont;
|
|
|
|
right = pbox->x2;
|
|
if(right <= drw_x + xoffset) goto mycont;
|
|
|
|
top = pbox->y1;
|
|
if(top >= drw_y + yoffset + height) goto mycont;
|
|
|
|
bottom = pbox->y2;
|
|
if(bottom <= drw_y + yoffset) goto mycont;
|
|
|
|
if(left < (drw_x + xoffset)) left = drw_x + xoffset;
|
|
if(right > (drw_x + xoffset + width)) right = drw_x + xoffset + width;
|
|
if(top < (drw_y + yoffset)) top = drw_y + yoffset;
|
|
if(bottom > (drw_y + yoffset + height)) bottom = drw_y + yoffset + height;
|
|
|
|
MyPacket.P12_DstX = left;
|
|
MyPacket.P12_DstY = top;
|
|
MyPacket.P12_RectWidth = right - left;
|
|
MyPacket.P12_RectHeight = bottom - top;
|
|
|
|
#if 0
|
|
#ifdef SISMERGED
|
|
if((first) && (pSiS->MergedFB)) {
|
|
int scrwidth = ((SiSMergedDisplayModePtr)pSiS->CurrentLayout.mode->Private)->CRT2->HDisplay;
|
|
int scrheight = ((SiSMergedDisplayModePtr)pSiS->CurrentLayout.mode->Private)->CRT2->VDisplay;
|
|
if( (right < pSiS->CRT2pScrn->frameX0) ||
|
|
(left >= pSiS->CRT2pScrn->frameX0 + scrwidth) ||
|
|
(bottom < pSiS->CRT2pScrn->frameY0) ||
|
|
(top >= pSiS->CRT2pScrn->frameY0 + scrheight) ) {
|
|
MyPacket.P12_Command |= pPriv->VBlankTriggerCRT1;
|
|
} else {
|
|
MyPacket.P12_Command |= pPriv->VBlankTriggerCRT2;
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
offsety = offsetuv = 0;
|
|
if(packed) {
|
|
if(pbox->y1 > drw_y + yoffset) {
|
|
offsetuv = (pbox->y1 - drw_y - yoffset) * srcPitch;
|
|
}
|
|
if(pbox->x1 > drw_x + xoffset) {
|
|
offsetuv += ((pbox->x1 - drw_x - xoffset) << 1);
|
|
if(offsetuv & 3) {
|
|
#if 0 /* Paint over covering object - no */
|
|
if(MyPacket.P12_DstX > 0) {
|
|
offsetuv &= ~3;
|
|
MyPacket.P12_DstX--;
|
|
MyPacket.P12_RectWidth++;
|
|
} else {
|
|
#endif
|
|
offsetuv = (offsetuv + 3) & ~3;
|
|
MyPacket.P12_DstX++;
|
|
MyPacket.P12_RectWidth--;
|
|
#if 0
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
} else {
|
|
if(pbox->y1 > drw_y + yoffset) {
|
|
offsety = (pbox->y1 - drw_y - yoffset) * srcPitch;
|
|
offsetuv = ((pbox->y1 - drw_y - yoffset) >> 1) * srcPitch;
|
|
}
|
|
if(pbox->x1 > drw_x + xoffset) {
|
|
offsety += (pbox->x1 - drw_x - xoffset);
|
|
offsetuv += (pbox->x1 - drw_x - xoffset);
|
|
if(offsetuv & 1) {
|
|
offsety++;
|
|
offsetuv++;
|
|
MyPacket.P12_DstX++;
|
|
MyPacket.P12_RectWidth--;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!MyPacket.P12_RectWidth) continue;
|
|
|
|
MyPacket.P12_YSrcAddr = pPriv->bufAddr[index][pPriv->currentBuf[index]] + offsety + FBOFFSET;
|
|
MyPacket.P12_UVSrcAddr = pPriv->bufAddr[index][pPriv->currentBuf[index]] + bytesize + offsetuv + FBOFFSET;
|
|
SISWriteBlitPacket(pSiS, (CARD32*)&MyPacket);
|
|
#if 0
|
|
MyPacket.P12_Command &= ~(pPriv->VBlankTriggerCRT1 | pPriv->VBlankTriggerCRT2);
|
|
#endif
|
|
first = FALSE;
|
|
mycont:
|
|
pbox++;
|
|
}
|
|
|
|
#if 0
|
|
{
|
|
int debug = 0;
|
|
while( (SIS_MMIO_IN16(pSiS->IOBase, Q_STATUS+2) & 0x8000) != 0x8000) { debug++; };
|
|
while( (SIS_MMIO_IN16(pSiS->IOBase, Q_STATUS+2) & 0x8000) != 0x8000) { debug++; };
|
|
xf86DrvMsg(0, X_INFO, "vsync %d, debug %d\n", pPriv->vsync, debug);
|
|
}
|
|
#endif
|
|
|
|
pPriv->currentBuf[index] ^= 1;
|
|
|
|
UpdateCurrentTime();
|
|
pPriv->freeTime[index] = currentTime.milliseconds + FREE_DELAY;
|
|
pPriv->videoStatus[index] = FREE_TIMER;
|
|
|
|
pSiS->VideoTimerCallback = SISVideoTimerCallback;
|
|
|
|
return Success;
|
|
}
|
|
|
|
static int
|
|
SISQueryImageAttributesBlit(
|
|
ScrnInfoPtr pScrn,
|
|
int id,
|
|
UShort *w, UShort *h,
|
|
int *pitches, int *offsets
|
|
){
|
|
int pitchY, pitchUV;
|
|
int size, sizeY, sizeUV;
|
|
|
|
if(*w > DummyEncodingBlit.width) *w = DummyEncodingBlit.width;
|
|
if(*h > DummyEncodingBlit.height) *h = DummyEncodingBlit.height;
|
|
|
|
switch(id) {
|
|
case PIXEL_FMT_YV12:
|
|
case PIXEL_FMT_I420:
|
|
*w = (*w + 7) & ~7;
|
|
*h = (*h + 1) & ~1;
|
|
pitchY = *w;
|
|
pitchUV = *w >> 1;
|
|
if(pitches) {
|
|
pitches[0] = pitchY;
|
|
pitches[1] = pitches[2] = pitchUV;
|
|
}
|
|
sizeY = pitchY * (*h);
|
|
sizeUV = pitchUV * ((*h) >> 1);
|
|
if(offsets) {
|
|
offsets[0] = 0;
|
|
offsets[1] = sizeY;
|
|
offsets[2] = sizeY + sizeUV;
|
|
}
|
|
size = sizeY + (sizeUV << 1);
|
|
break;
|
|
case PIXEL_FMT_NV12:
|
|
case PIXEL_FMT_NV21:
|
|
*w = (*w + 7) & ~7;
|
|
pitchY = *w;
|
|
pitchUV = *w;
|
|
if(pitches) {
|
|
pitches[0] = pitchY;
|
|
pitches[1] = pitchUV;
|
|
}
|
|
sizeY = pitchY * (*h);
|
|
sizeUV = pitchUV * ((*h) >> 1);
|
|
if(offsets) {
|
|
offsets[0] = 0;
|
|
offsets[1] = sizeY;
|
|
}
|
|
size = sizeY + (sizeUV << 1);
|
|
break;
|
|
case PIXEL_FMT_YUY2:
|
|
case PIXEL_FMT_UYVY:
|
|
case PIXEL_FMT_YVYU:
|
|
default:
|
|
*w = (*w + 1) & ~1;
|
|
pitchY = *w << 1;
|
|
if(pitches) pitches[0] = pitchY;
|
|
if(offsets) offsets[0] = 0;
|
|
size = pitchY * (*h);
|
|
break;
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
static void
|
|
SISQueryBestSizeBlit(
|
|
ScrnInfoPtr pScrn,
|
|
Bool motion,
|
|
short vid_w, short vid_h,
|
|
short drw_w, short drw_h,
|
|
unsigned int *p_w, unsigned int *p_h,
|
|
ULong index
|
|
){
|
|
/* We cannot scale */
|
|
*p_w = vid_w;
|
|
*p_h = vid_h;
|
|
}
|
|
#endif /* INCL_YUV */
|
|
|
|
/*****************************************/
|
|
/* TIMER CALLBACK */
|
|
/*****************************************/
|
|
|
|
static void
|
|
SISVideoTimerCallback(ScrnInfoPtr pScrn, Time now)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
SISPortPrivPtr pPriv = NULL;
|
|
#ifdef INCL_YUV_BLIT_ADAPTOR
|
|
SISBPortPrivPtr pPrivBlit = NULL;
|
|
#endif
|
|
UChar sridx, cridx;
|
|
Bool setcallback = FALSE;
|
|
|
|
if(!pScrn->vtSema) return;
|
|
|
|
if(pSiS->adaptor) {
|
|
pPriv = GET_PORT_PRIVATE(pScrn);
|
|
if(!pPriv->videoStatus) pPriv = NULL;
|
|
}
|
|
|
|
if(pPriv) {
|
|
if(pPriv->videoStatus & TIMER_MASK) {
|
|
if(pPriv->videoStatus & OFF_TIMER) {
|
|
setcallback = TRUE;
|
|
if(pPriv->offTime < now) {
|
|
/* Turn off the overlay */
|
|
sridx = inSISREG(SISSR); cridx = inSISREG(SISCR);
|
|
close_overlay(pSiS, pPriv);
|
|
outSISREG(SISSR, sridx); outSISREG(SISCR, cridx);
|
|
pPriv->mustwait = 1;
|
|
pPriv->videoStatus = FREE_TIMER;
|
|
pPriv->freeTime = now + FREE_DELAY;
|
|
}
|
|
} else if(pPriv->videoStatus & FREE_TIMER) {
|
|
if(pPriv->freeTime < now) {
|
|
SISFreeFBMemory(pScrn, &pPriv->handle);
|
|
pPriv->mustwait = 1;
|
|
pPriv->videoStatus = 0;
|
|
} else {
|
|
setcallback = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef INCL_YUV_BLIT_ADAPTOR
|
|
if(pSiS->blitadaptor) {
|
|
int i;
|
|
pPrivBlit = (SISBPortPrivPtr)(pSiS->blitPriv);
|
|
for(i = 0; i < NUM_BLIT_PORTS; i++) {
|
|
if(pPrivBlit->videoStatus[i] & FREE_TIMER) {
|
|
if(pPrivBlit->freeTime[i] < now) {
|
|
SISFreeFBMemory(pScrn, &pPrivBlit->handle[i]);
|
|
pPrivBlit->videoStatus[i] = 0;
|
|
} else {
|
|
setcallback = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
pSiS->VideoTimerCallback = (setcallback) ? SISVideoTimerCallback : NULL;
|
|
}
|
|
|