diff options
Diffstat (limited to 'src/sis_video.c')
-rw-r--r-- | src/sis_video.c | 2996 |
1 files changed, 2015 insertions, 981 deletions
diff --git a/src/sis_video.c b/src/sis_video.c index df172d2..35741fc 100644 --- a/src/sis_video.c +++ b/src/sis_video.c @@ -1,43 +1,44 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/sis_video.c,v 1.27 2003/09/04 15:32:45 twini Exp $ */ +/* $XFree86$ */ +/* $XdotOrg$ */ /* * Xv driver for SiS 300, 315 and 330 series. * - * Copyright 2002, 2003 by Thomas Winischhofer, Vienna, Austria. - * All Rights Reserved. + * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria. * - * Basic structure based on the mga Xv driver by Mark Vojkovich - * and i810 Xv driver by Jonathan Bian <jonathan.bian@intel.com>. - * - * Formerly based on a mostly non-working fragment for the 630 by - * Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan. + * 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. * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of the copyright holder not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. The copyright holder makes no representations - * about the suitability of this software for any purpose. It is provided - * "as is" without express or implied warranty. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED 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. * - * THE COPYRIGHT HOLDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. + * Author: Thomas Winischhofer <thomas@winischhofer.net> * - * Authors: - * Thomas Winischhofer <thomas@winischhofer.net>: - * (Original code fragment for 630 by - * Sung-Ching Lin <sclin@sis.com.tw>) + * 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. * - * This supports the following chipsets: + * 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) @@ -45,11 +46,12 @@ * 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.) - * SiS660: ? Full register range, two overlays (one used for CRT1, one for CRT2) ? + * SiS661/741/760: Full register range, two overlays (one used for CRT1, one for CRT2) + * SiS340: - not finished yet; dda stuff missing - 1 overlay. Extended registers for DDA * * Help for reading the code: - * 315/550/650/740/M650/651/330/660 = SIS_315_VGA - * 300/630/730 = SIS_300_VGA + * 315/550/650/740/M650/651/330/661/741/760 = SIS_315_VGA + * 300/630/730 = SIS_300_VGA * For chipsets with 2 overlays, hasTwoOverlays will be true * * Notes on display modes: @@ -58,14 +60,14 @@ * 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) + * 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) + * 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. @@ -73,14 +75,23 @@ * 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) + * 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. + * */ - + #include "xf86.h" #include "xf86_OSproc.h" #include "xf86Resources.h" @@ -95,12 +106,15 @@ #include "xf86xv.h" #include "Xv.h" #include "xaa.h" -#include "xaalocal.h" #include "dixstruct.h" #include "fourcc.h" #include "sis_regs.h" +#ifdef INCL_YUV_BLIT_ADAPTOR +#include "sis310_accel.h" +#endif + static XF86VideoAdaptorPtr SISSetupImageVideo(ScreenPtr); static void SISStopVideo(ScrnInfoPtr, pointer, Bool); static int SISSetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer); @@ -116,8 +130,22 @@ static void SISVideoTimerCallback(ScrnInfoPtr pScrn, Time now); static void SISInitOffscreenImages(ScreenPtr pScrn); extern BOOLEAN SiSBridgeIsInSlaveMode(ScrnInfoPtr pScrn); -#define OFF_DELAY 200 /* milliseconds */ -#define FREE_DELAY 60000 +#ifdef INCL_YUV_BLIT_ADAPTOR +static XF86VideoAdaptorPtr SISSetupBlitVideo(ScreenPtr); +static void SISStopVideoBlit(ScrnInfoPtr, unsigned long, Bool); +static int SISSetPortAttributeBlit(ScrnInfoPtr, Atom, INT32, unsigned long); +static int SISGetPortAttributeBlit(ScrnInfoPtr, Atom ,INT32 *, unsigned long); +static void SISQueryBestSizeBlit(ScrnInfoPtr, Bool, short, short, short, + short, unsigned int *,unsigned int *, unsigned long); +static int SISPutImageBlit( ScrnInfoPtr, + short, short, short, short, short, short, short, short, + int, unsigned char*, short, short, Bool, RegionPtr, unsigned long); +static int SISQueryImageAttributesBlit(ScrnInfoPtr, + int, unsigned short *, unsigned short *, int *, int *); +#endif + +#define OFF_DELAY 200 /* milliseconds */ +#define FREE_DELAY 30000 #define OFF_TIMER 0x01 #define FREE_TIMER 0x02 @@ -125,7 +153,7 @@ extern BOOLEAN SiSBridgeIsInSlaveMode(ScrnInfoPtr pScrn); #define TIMER_MASK (OFF_TIMER | FREE_TIMER) -#define WATCHDOG_DELAY 500000 /* Watchdog counter for Vertical Restrace waiting */ +#define WATCHDOG_DELAY 200000 /* Watchdog counter for Vertical Restrace waiting */ #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) @@ -135,6 +163,7 @@ extern BOOLEAN SiSBridgeIsInSlaveMode(ScrnInfoPtr pScrn); #define IMAGE_MAX_HEIGHT_300 576 #define IMAGE_MAX_WIDTH_315 1920 #define IMAGE_MAX_HEIGHT_315 1080 +#define IMAGE_MAX_WIDTH_340 1920 /* ? */ #define OVERLAY_MIN_WIDTH 32 /* Minimum overlay sizes */ #define OVERLAY_MIN_HEIGHT 24 @@ -145,11 +174,13 @@ extern BOOLEAN SiSBridgeIsInSlaveMode(ScrnInfoPtr pScrn); #define LINEBUFLIMIT1 384 /* Limits at which line buffers must be merged */ #define LINEBUFLIMIT2 720 +#define LINEBUFLIMIT3 576 +#define LINEBUFLIMIT4 1280 /* 340 */ #ifdef SISDUALHEAD #define HEADOFFSET (pSiS->dhmOffset) #endif - + /* Note on "MIRROR": * When using VESA on machines with an enabled video bridge, this means * a real mirror. CRT1 and CRT2 have the exact same resolution and @@ -160,146 +191,6 @@ extern BOOLEAN SiSBridgeIsInSlaveMode(ScrnInfoPtr pScrn); * refresh rate. */ -/**************************************************************************** - * Raw register access : These routines directly interact with the sis's - * control aperature. Must not be called until after - * the board's pci memory has been mapped. - ****************************************************************************/ - -#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) -{ - CARD8 old; - inSISIDXREG(SISVID, reg, old); - data = (data & mask) | (old & (~mask)); - outSISIDXREG(SISVID, reg, data); -} - -static void setsrregmask(SISPtr pSiS, CARD8 reg, CARD8 data, CARD8 mask) -{ - CARD8 old; - - inSISIDXREG(SISSR, reg, old); - data = (data & mask) | (old & (~mask)); - outSISIDXREG(SISSR, reg, data); -} - -/* VBlank */ -static CARD8 vblank_active_CRT1(SISPtr pSiS) -{ - return (inSISREG(SISINPSTAT) & 0x08); -} - -static CARD8 vblank_active_CRT2(SISPtr pSiS) -{ - CARD8 ret; - if(pSiS->VGAEngine == SIS_315_VGA) { - inSISIDXREG(SISPART1, Index_310_CRT2_FC_VR, ret); - } else { - inSISIDXREG(SISPART1, Index_CRT2_FC_VR, ret); - } - return((ret & 0x02) ^ 0x02); -} - -/* Scanline - unused */ -#if 0 -static CARD32 get_scanline_CRT1(SISPtr pSiS) -{ - CARD32 line; - - _siswrite (pSiS, REG_PRIM_CRT_COUNTER, 0x00000001); - line = _sisread (pSiS, REG_PRIM_CRT_COUNTER); - - return ((line >> 16) & 0x07FF); -} - -static CARD32 get_scanline_CRT2(SISPtr pSiS) -{ - CARD32 line; - - line = (CARD32)(getsisreg(pSiS, SISPART1, Index_CRT2_FC_VCount1) & 0x70) * 16 - + getsisreg(pSiS, SISPART1, Index_CRT2_FC_VCount); - - return line; -} -#endif - -void SISInitVideo(ScreenPtr pScreen) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; - XF86VideoAdaptorPtr newAdaptor = NULL; - int num_adaptors; - - newAdaptor = SISSetupImageVideo(pScreen); - if(newAdaptor) - SISInitOffscreenImages(pScreen); - - num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); - - if(newAdaptor) { - if(!num_adaptors) { - num_adaptors = 1; - adaptors = &newAdaptor; - } else { - /* need to free this someplace */ - newAdaptors = xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*)); - if(newAdaptors) { - memcpy(newAdaptors, adaptors, num_adaptors * - sizeof(XF86VideoAdaptorPtr)); - newAdaptors[num_adaptors] = newAdaptor; - adaptors = newAdaptors; - num_adaptors++; - } - } - } - - if(num_adaptors) - xf86XVScreenInit(pScreen, adaptors, num_adaptors); - - if(newAdaptors) - xfree(newAdaptors); -} - -/* client libraries expect an encoding */ -static XF86VideoEncodingRec DummyEncoding = -{ - 0, - "XV_IMAGE", - 0, 0, /* Will be filled in */ - {1, 1} -}; - #define NUM_FORMATS 3 static XF86VideoFormatRec SISFormats[NUM_FORMATS] = @@ -319,6 +210,9 @@ static char sisxvsetdefaults[] = "XV_SET_DEFAULTS"; static char sisxvswitchcrt[] = "XV_SWITCHCRT"; static char sisxvtvxposition[] = "XV_TVXPOSITION"; static char sisxvtvyposition[] = "XV_TVYPOSITION"; +static char sisxvgammared[] = "XV_GAMMA_RED"; +static char sisxvgammagreen[] = "XV_GAMMA_GREEN"; +static char sisxvgammablue[] = "XV_GAMMA_BLUE"; static char sisxvdisablegfx[] = "XV_DISABLE_GRAPHICS"; static char sisxvdisablegfxlr[] = "XV_DISABLE_GRAPHICS_LR"; static char sisxvdisablecolorkey[] = "XV_DISABLE_COLORKEY"; @@ -339,6 +233,7 @@ static char sisxvsdquerydetecteddevices[] = "XV_SD_QUERYDETECTEDDEVICES"; static char sisxvsdcrt1status[] = "XV_SD_CRT1STATUS"; static char sisxvsdcheckmodeindexforcrt2[] = "XV_SD_CHECKMODEINDEXFORCRT2"; static char sisxvsdresultcheckmodeindexforcrt2[] = "XV_SD_RESULTCHECKMODEINDEXFORCRT2"; +static char sisxvsdredetectcrt2[] = "XV_SD_REDETECTCRT2DEVICES"; static char sisxvsdsisantiflicker[] = "XV_SD_SISANTIFLICKER"; static char sisxvsdsissaturation[] = "XV_SD_SISSATURATION"; static char sisxvsdsisedgeenhance[] = "XV_SD_SISEDGEENHANCE"; @@ -362,11 +257,44 @@ static char sisxvsdstorebrib[] = "XV_SD_STOREDGAMMABRIB"; static char sisxvsdstorepbrir[] = "XV_SD_STOREDGAMMAPBRIR"; static char sisxvsdstorepbrig[] = "XV_SD_STOREDGAMMAPBRIG"; static char sisxvsdstorepbrib[] = "XV_SD_STOREDGAMMAPBRIB"; +static char sisxvsdstorebrir2[] = "XV_SD_STOREDGAMMABRIR2"; +static char sisxvsdstorebrig2[] = "XV_SD_STOREDGAMMABRIG2"; +static char sisxvsdstorebrib2[] = "XV_SD_STOREDGAMMABRIB2"; +static char sisxvsdstorepbrir2[] = "XV_SD_STOREDGAMMAPBRIR2"; +static char sisxvsdstorepbrig2[] = "XV_SD_STOREDGAMMAPBRIG2"; +static char sisxvsdstorepbrib2[] = "XV_SD_STOREDGAMMAPBRIB2"; static char sisxvsdhidehwcursor[] = "XV_SD_HIDEHWCURSOR"; +static char sisxvsdpanelmode[] = "XV_SD_PANELMODE"; +#ifdef INCL_YUV_BLIT_ADAPTOR +static char sisxvvsync[] = "XV_SYNC_TO_VBLANK"; +#endif +#ifdef TWDEBUG +static char sisxvsetreg[] = "XV_SD_SETREG"; +#endif + +/***********************************************/ +/* OVERLAY ADAPTOR */ +/***********************************************/ + +#define GET_PORT_PRIVATE(pScrn) \ + (SISPortPrivPtr)((SISPTR(pScrn))->adaptor->pPortPrivates[0].ptr) + +/* client libraries expect an encoding */ +static XF86VideoEncodingRec DummyEncoding = +{ + 0, + "XV_IMAGE", + 0, 0, /* Will be filled in */ + {1, 1} +}; #ifndef SIS_CP -#define NUM_ATTRIBUTES_300 50 -#define NUM_ATTRIBUTES_315 53 +#define NUM_ATTRIBUTES_300 58 +#ifdef TWDEBUG +#define NUM_ATTRIBUTES_315 65 +#else +#define NUM_ATTRIBUTES_315 64 +#endif #endif static XF86AttributeRec SISAttributes_300[NUM_ATTRIBUTES_300] = @@ -398,6 +326,7 @@ static XF86AttributeRec SISAttributes_300[NUM_ATTRIBUTES_300] = {XvSettable | XvGettable, 0, 1, sisxvsdcrt1status}, {XvSettable , 0, 0xffffffff, sisxvsdcheckmodeindexforcrt2}, { XvGettable, 0, 0xffffffff, sisxvsdresultcheckmodeindexforcrt2}, + {XvSettable , 0, 0, sisxvsdredetectcrt2}, {XvSettable | XvGettable, 0, 4, sisxvsdsisantiflicker}, {XvSettable | XvGettable, 0, 15, sisxvsdsissaturation}, {XvSettable | XvGettable, 0, 15, sisxvsdsisedgeenhance}, @@ -421,6 +350,13 @@ static XF86AttributeRec SISAttributes_300[NUM_ATTRIBUTES_300] = {XvSettable | XvGettable, 100, 10000, sisxvsdstorepbrir}, {XvSettable | XvGettable, 100, 10000, sisxvsdstorepbrig}, {XvSettable | XvGettable, 100, 10000, sisxvsdstorepbrib}, + {XvSettable | XvGettable, 100, 10000, sisxvsdstorebrir2}, + {XvSettable | XvGettable, 100, 10000, sisxvsdstorebrig2}, + {XvSettable | XvGettable, 100, 10000, sisxvsdstorebrib2}, + {XvSettable | XvGettable, 100, 10000, sisxvsdstorepbrir2}, + {XvSettable | XvGettable, 100, 10000, sisxvsdstorepbrig2}, + {XvSettable | XvGettable, 100, 10000, sisxvsdstorepbrib2}, + {XvSettable | XvGettable, 0, 15, sisxvsdpanelmode}, #ifdef SIS_CP SIS_CP_VIDEO_ATTRIBUTES #endif @@ -437,12 +373,14 @@ static XF86AttributeRec SISAttributes_315[NUM_ATTRIBUTES_315] = {XvSettable , 0, 0, sisxvsetdefaults}, {XvSettable | XvGettable, -32, 32, sisxvtvxposition}, {XvSettable | XvGettable, -32, 32, sisxvtvyposition}, + {XvSettable | XvGettable, 100, 10000, sisxvgammared}, + {XvSettable | XvGettable, 100, 10000, sisxvgammagreen}, + {XvSettable | XvGettable, 100, 10000, sisxvgammablue}, {XvSettable | XvGettable, 0, 1, sisxvdisablegfx}, {XvSettable | XvGettable, 0, 1, sisxvdisablegfxlr}, {XvSettable | XvGettable, 0, 1, sisxvdisablecolorkey}, {XvSettable | XvGettable, 0, 1, sisxvusechromakey}, {XvSettable | XvGettable, 0, 1, sisxvinsidechromakey}, -/* {XvSettable | XvGettable, 0, 1, sisxvyuvchromakey}, - NO, Chromakey format = Source format */ {XvSettable | XvGettable, 0, (1 << 24) - 1, sisxvchromamin}, {XvSettable | XvGettable, 0, (1 << 24) - 1, sisxvchromamax}, { XvGettable, 0, 0xffffffff, sisxvqueryvbflags}, @@ -457,6 +395,7 @@ static XF86AttributeRec SISAttributes_315[NUM_ATTRIBUTES_315] = {XvSettable | XvGettable, 0, 1, sisxvsdcrt1status}, {XvSettable , 0, 0xffffffff, sisxvsdcheckmodeindexforcrt2}, { XvGettable, 0, 0xffffffff, sisxvsdresultcheckmodeindexforcrt2}, + {XvSettable , 0, 0, sisxvsdredetectcrt2}, {XvSettable | XvGettable, 0, 4, sisxvsdsisantiflicker}, {XvSettable | XvGettable, 0, 15, sisxvsdsissaturation}, {XvSettable | XvGettable, 0, 15, sisxvsdsisedgeenhance}, @@ -470,7 +409,7 @@ static XF86AttributeRec SISAttributes_315[NUM_ATTRIBUTES_315] = {XvSettable | XvGettable, 0, 15, sisxvsdchlumaflickerfilter}, {XvSettable | XvGettable, 0, 1, sisxvsdchcvbscolor}, {XvSettable | XvGettable, 0, 3, sisxvsdchoverscan}, - {XvSettable | XvGettable, 0, 3, sisxvsdenablegamma}, + {XvSettable | XvGettable, 0, 7, sisxvsdenablegamma}, {XvSettable | XvGettable, -16, 16, sisxvsdtvxscale}, {XvSettable | XvGettable, -4, 3, sisxvsdtvyscale}, { XvGettable, 0, 0xffffffff, sisxvsdgetscreensize}, @@ -480,7 +419,17 @@ static XF86AttributeRec SISAttributes_315[NUM_ATTRIBUTES_315] = {XvSettable | XvGettable, 100, 10000, sisxvsdstorepbrir}, {XvSettable | XvGettable, 100, 10000, sisxvsdstorepbrig}, {XvSettable | XvGettable, 100, 10000, sisxvsdstorepbrib}, + {XvSettable | XvGettable, 100, 10000, sisxvsdstorebrir2}, + {XvSettable | XvGettable, 100, 10000, sisxvsdstorebrig2}, + {XvSettable | XvGettable, 100, 10000, sisxvsdstorebrib2}, + {XvSettable | XvGettable, 100, 10000, sisxvsdstorepbrir2}, + {XvSettable | XvGettable, 100, 10000, sisxvsdstorepbrig2}, + {XvSettable | XvGettable, 100, 10000, sisxvsdstorepbrib2}, {XvSettable | XvGettable, 0, 1, sisxvsdhidehwcursor}, + {XvSettable | XvGettable, 0, 15, sisxvsdpanelmode}, +#ifdef TWDEBUG + {XvSettable , 0, 0xffffffff, sisxvsetreg}, +#endif #ifdef SIS_CP SIS_CP_VIDEO_ATTRIBUTES #endif @@ -488,17 +437,18 @@ static XF86AttributeRec SISAttributes_315[NUM_ATTRIBUTES_315] = }; #define NUM_IMAGES_300 6 -#define NUM_IMAGES_315 7 /* NV12 only - but does not work */ +#define NUM_IMAGES_315 7 /* basically NV12 only - but does not work */ #define NUM_IMAGES_330 9 /* NV12 and NV21 */ + #define PIXEL_FMT_YV12 FOURCC_YV12 /* 0x32315659 */ #define PIXEL_FMT_UYVY FOURCC_UYVY /* 0x59565955 */ #define PIXEL_FMT_YUY2 FOURCC_YUY2 /* 0x32595559 */ #define PIXEL_FMT_I420 FOURCC_I420 /* 0x30323449 */ #define PIXEL_FMT_RGB5 0x35315652 #define PIXEL_FMT_RGB6 0x36315652 -#define PIXEL_FMT_YVYU 0x55595659 /* 315/330 only */ -#define PIXEL_FMT_NV12 0x3231564e /* 330 only */ -#define PIXEL_FMT_NV21 0x3132564e /* 330 only */ +#define PIXEL_FMT_YVYU 0x55595659 /* 315/330+ only */ +#define PIXEL_FMT_NV12 0x3231564e /* 330+ only */ +#define PIXEL_FMT_NV21 0x3132564e /* 330+ only */ /* TODO: */ #define PIXEL_FMT_RAW8 0x38574152 @@ -519,7 +469,6 @@ static XF86ImageRec SISImages[NUM_IMAGES_330] = 16, XvPacked, 1, -/* 15, 0x001F, 0x03E0, 0x7C00, - incorrect! */ 15, 0x7C00, 0x03E0, 0x001F, 0, 0, 0, 0, 0, 0, @@ -537,7 +486,6 @@ static XF86ImageRec SISImages[NUM_IMAGES_330] = 16, XvPacked, 1, -/* 16, 0x001F, 0x07E0, 0xF800, - incorrect! */ 16, 0xF800, 0x07E0, 0x001F, 0, 0, 0, 0, 0, 0, @@ -600,6 +548,76 @@ static XF86ImageRec SISImages[NUM_IMAGES_330] = }; typedef struct { + FBLinearPtr linear; + CARD32 bufAddr[2]; + + unsigned char currentBuf; + + short drw_x, drw_y, drw_w, drw_h; + short src_x, src_y, src_w, src_h; + int id; + short srcPitch, height; + + char brightness; + unsigned char contrast; + char hue; + short saturation; + + RegionRec clip; + CARD32 colorKey; + Bool autopaintColorKey; + + Bool disablegfx; + Bool disablegfxlr; + + Bool usechromakey; + Bool insidechromakey, yuvchromakey; + CARD32 chromamin, chromamax; + + CARD32 videoStatus; + BOOLEAN overlayStatus; + Time offTime; + Time freeTime; + + CARD32 displayMode; + Bool bridgeIsSlave; + + Bool hasTwoOverlays; /* Chipset has two overlays */ + Bool dualHeadMode; /* We're running in DHM */ + + Bool NoOverlay; + Bool PrevOverlay; + + Bool AllowSwitchCRT; + int crtnum; /* 0=CRT1, 1=CRT2 */ + + Bool needToScale; /* Need to scale video */ + + int shiftValue; /* 315/330 series need word addr/pitch, 300 series double word */ + + short linebufMergeLimit; + CARD8 linebufmask; + + short oldx1, oldx2, oldy1, oldy2; +#ifdef SISMERGED + short oldx1_2, oldx2_2, oldy1_2, oldy2_2; +#endif + int mustwait; + + Bool grabbedByV4L; /* V4L stuff */ + int pitch; + int offset; + + int modeflags; /* Flags field of current display mode */ + + int tvxpos, tvypos; + Bool updatetvxpos, updatetvypos; + + Bool is340; + +} SISPortPrivRec, *SISPortPrivPtr; + +typedef struct { int pixelFormat; CARD16 pitch; @@ -622,7 +640,7 @@ typedef struct { CARD16 SCREENheight; - CARD8 lineBufSize; + CARD16 lineBufSize; DisplayModePtr currentmode; @@ -640,7 +658,7 @@ typedef struct { CARD32 PSV2; CARD32 PSU2; CARD16 SCREENheight2; - CARD8 lineBufSize2; + CARD16 lineBufSize2; DisplayModePtr currentmode2; @@ -648,105 +666,357 @@ typedef struct { #endif CARD8 bobEnable; + + CARD8 planar; + CARD8 planar_shiftpitch; CARD8 contrastCtrl; CARD8 contrastFactor; + + CARD16 oldLine, oldtop; - CARD8 (*VBlankActiveFunc)(SISPtr); + CARD8 (*VBlankActiveFunc)(SISPtr, SISPortPrivPtr); #if 0 CARD32 (*GetScanLineFunc)(SISPtr pSiS); #endif -#if 0 - /* The following are not used yet */ - CARD16 SubPictHUSF; /* Subpicture scaling */ - CARD16 SubpictVUSF; - CARD8 SubpictIntBit; - CARD8 SubPictwHPre; - CARD16 SubPictsrcW; /* Subpicture source width */ - CARD16 SubPictsrcH; /* Subpicture source height */ - BoxRec SubPictdstBox; /* SubPicture destination box */ - CARD32 SubPictAddr; /* SubPicture address */ - CARD32 SubPictPitch; /* SubPicture pitch */ - CARD32 SubPictOrigPitch; /* SubPicture real pitch (needed for scaling twice) */ - CARD32 SubPictPreset; /* Subpicture Preset */ - - CARD32 MPEG_Y; /* MPEG Y Buffer Addr */ - CARD32 MPEG_UV; /* MPEG UV Buffer Addr */ -#endif - } SISOverlayRec, *SISOverlayPtr; -typedef struct { - FBLinearPtr linear; - CARD32 bufAddr[2]; +/***********************************************/ +/* BLITTER ADAPTOR */ +/***********************************************/ - unsigned char currentBuf; +#ifdef INCL_YUV_BLIT_ADAPTOR - short drw_x, drw_y, drw_w, drw_h; - short src_x, src_y, src_w, src_h; - int id; - short srcPitch, height; - - char brightness; - unsigned char contrast; - char hue; - char saturation; +#define NUM_BLIT_PORTS 16 - RegionRec clip; - CARD32 colorKey; - Bool autopaintColorKey; +static XF86VideoEncodingRec DummyEncodingBlit = +{ + 0, + "XV_IMAGE", + 2046, 2046, + {1, 1} +}; - Bool disablegfx; - Bool disablegfxlr; +#define NUM_ATTRIBUTES_BLIT 2 - Bool usechromakey; - Bool insidechromakey, yuvchromakey; - CARD32 chromamin, chromamax; +static XF86AttributeRec SISAttributes_Blit[NUM_ATTRIBUTES_BLIT] = +{ + {XvSettable | XvGettable, 0, 1, sisxvvsync}, + {XvSettable , 0, 0, sisxvsetdefaults} +}; - CARD32 videoStatus; - BOOLEAN overlayStatus; - Time offTime; - Time freeTime; +#define NUM_IMAGES_BLIT 7 - CARD32 displayMode; - Bool bridgeIsSlave; +static XF86ImageRec SISImagesBlit[NUM_IMAGES_BLIT] = +{ - Bool hasTwoOverlays; /* Chipset has two overlays */ - Bool dualHeadMode; /* We're running in DHM */ + XVIMAGE_YUY2, + XVIMAGE_YV12, + XVIMAGE_UYVY, + XVIMAGE_I420, + { /* YVYU */ + PIXEL_FMT_YVYU, \ + XvYUV, \ + LSBFirst, \ + {'Y','V','Y','U', + 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, + 16, + XvPacked, + 1, + 0, 0, 0, 0, + 8, 8, 8, + 1, 2, 2, + 1, 1, 1, + {'Y','V','Y','U', + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + XvTopToBottom + }, + { /* NV12 */ + PIXEL_FMT_NV12, + XvYUV, + LSBFirst, + {'N','V','1','2', + 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, + 12, + XvPlanar, + 2, + 0, 0, 0, 0, + 8, 8, 8, + 1, 2, 2, + 1, 2, 2, + {'Y','U','V',0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + XvTopToBottom + }, + { /* NV21 */ + PIXEL_FMT_NV21, + XvYUV, + LSBFirst, + {'N','V','2','1', + 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, + 12, + XvPlanar, + 2, + 0, 0, 0, 0, + 8, 8, 8, + 1, 2, 2, + 1, 2, 2, + {'Y','V','U',0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + XvTopToBottom + } +}; + +typedef struct { + FBLinearPtr linear[NUM_BLIT_PORTS]; + CARD32 bufAddr[NUM_BLIT_PORTS][2]; + + unsigned char currentBuf[NUM_BLIT_PORTS]; - Bool NoOverlay; - Bool PrevOverlay; + RegionRec blitClip[NUM_BLIT_PORTS]; - Bool AllowSwitchCRT; - int crtnum; /* 0=CRT1, 1=CRT2 */ + CARD32 videoStatus[NUM_BLIT_PORTS]; + Time freeTime[NUM_BLIT_PORTS]; + + Bool vsync; + CARD32 AccelCmd; + CARD32 VBlankTriggerCRT1, VBlankTriggerCRT2; +} SISBPortPrivRec, *SISBPortPrivPtr; - Bool needToScale; /* Need to scale video */ +#endif /* INCL_BLIT */ - int shiftValue; /* 315/330 series need word addr/pitch, 300 series double word */ +/**************************************************************************** + * Raw register access : These routines directly interact with the sis's + * control aperature. Must not be called until after + * the board's pci memory has been mapped. + ****************************************************************************/ - short linebufMergeLimit; - CARD8 linebufmask; +#if 0 +static CARD32 _sisread(SISPtr pSiS, CARD32 reg) +{ + return *(pSiS->IOBase + reg); +} - short oldx1, oldx2, oldy1, oldy2; -#ifdef SISMERGED - short oldx1_2, oldx2_2, oldy1_2, oldy2_2; +static void _siswrite(SISPtr pSiS, CARD32 reg, CARD32 data) +{ + *(pSiS->IOBase + reg) = data; +} #endif - int mustwait; - Bool grabbedByV4L; /* V4L stuff */ - int pitch; - int offset; +static CARD8 getsrreg(SISPtr pSiS, CARD8 reg) +{ + CARD8 ret; + inSISIDXREG(SISSR, reg, ret); + return(ret); +} - int modeflags; /* Flags field of current display mode */ +static CARD8 getvideoreg(SISPtr pSiS, CARD8 reg) +{ + CARD8 ret; + inSISIDXREG(SISVID, reg, ret); + return(ret); +} - int tvxpos, tvypos; - Bool updatetvxpos, updatetvypos; +static __inline void setvideoreg(SISPtr pSiS, CARD8 reg, CARD8 data) +{ + outSISIDXREG(SISVID, reg, data); +} -} SISPortPrivRec, *SISPortPrivPtr; +static __inline void setvideoregmask(SISPtr pSiS, CARD8 reg, CARD8 data, CARD8 mask) +{ + CARD8 old; + inSISIDXREG(SISVID, reg, old); + data = (data & mask) | (old & (~mask)); + outSISIDXREG(SISVID, reg, data); +} -#define GET_PORT_PRIVATE(pScrn) \ - (SISPortPrivPtr)((SISPTR(pScrn))->adaptor->pPortPrivates[0].ptr) +static void setsrregmask(SISPtr pSiS, CARD8 reg, CARD8 data, CARD8 mask) +{ + CARD8 old; + + inSISIDXREG(SISSR, reg, old); + data = (data & mask) | (old & (~mask)); + outSISIDXREG(SISSR, reg, data); +} + +/* 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 + +#if 1 +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))); +} +#endif + +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; + unsigned char backup = getsrreg(pSiS, 0x1f); + setsrregmask(pSiS, 0x1f, 0x08, 0x18); + for(i = 0; i <= 255; i++) { + MMIO_OUT32(pSiS->IOBase, 0x8570, + (i << 24) | + (pSiS->XvGammaRampBlue[i] << 16) | + (pSiS->XvGammaRampGreen[i] << 8) | + pSiS->XvGammaRampRed[i]); + } + setsrregmask(pSiS, 0x1f, backup, 0xff); +} + +static void +SiSUpdateXvGamma(SISPtr pSiS, SISPortPrivPtr pPriv) +{ + unsigned char 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); +} + +void SISInitVideo(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; +#ifdef INCL_YUV_BLIT_ADAPTOR + SISPtr pSiS = SISPTR(pScrn); +#endif + 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->sishw_ext.jChipType >= 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); + } +} static void SISSetPortDefaults(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) @@ -757,7 +1027,6 @@ SISSetPortDefaults(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) #endif pPriv->colorKey = pSiS->colorKey = 0x000101fe; - pPriv->videoStatus = 0; pPriv->brightness = pSiS->XvDefBri; pPriv->contrast = pSiS->XvDefCon; pPriv->hue = pSiS->XvDefHue; @@ -789,12 +1058,19 @@ SISSetPortDefaults(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) #ifdef SIS_CP SIS_CP_VIDEO_DEF #endif - if(pPriv->dualHeadMode) + if(pPriv->dualHeadMode) { +#ifdef SISDUALHEAD pPriv->crtnum = pSiSEnt->curxvcrtnum = pSiSEnt->XvOnCRT2 ? 1 : 0; - else +#endif + } else pPriv->crtnum = pSiS->XvOnCRT2 ? 1 : 0; + + pSiS->XvGammaRed = pSiS->XvGammaRedDef; + pSiS->XvGammaGreen = pSiS->XvGammaGreenDef; + pSiS->XvGammaBlue = pSiS->XvGammaBlueDef; + SiSUpdateXvGamma(pSiS, pPriv); } static void @@ -813,7 +1089,7 @@ SISResetVideo(ScrnInfoPtr pScrn) 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) */ @@ -848,17 +1124,29 @@ SISResetVideo(ScrnInfoPtr pScrn) 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_SIS340) { + setvideoregmask(pSiS, 0xb5, 0x00, 0x01); /* Threshold high? */ + setvideoregmask(pSiS, 0xb6, 0x00, 0x01); + } - if((pSiS->Chipset == PCI_CHIP_SIS330) || (pSiS->Chipset == PCI_CHIP_SIS660)) { - /* What does this do? */ + if(pSiS->Chipset == PCI_CHIP_SIS330) { /* 340? */ setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x00, 0x10); + } else if(pSiS->Chipset == PCI_CHIP_SIS660) { + setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x00, 0xE0); + } + if(pSiS->sishw_ext.jChipType == SIS_661) { + setvideoregmask(pSiS, Index_VI_V_Buf_Start_Over, 0x2c, 0x3c); } - if(pSiS->ChipFlags & SiSCF_Is65x) { + if((pSiS->ChipFlags & SiSCF_Is65x) || (pSiS->Chipset == PCI_CHIP_SIS660)) { 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/652/653, 660 */ + /* Initialize second overlay (CRT2) - only for 300, 630/730, 550, M650/651, 661/741/660/760 */ if(pPriv->hasTwoOverlays) { if(pSiS->VGAEngine == SIS_300_VGA) { @@ -878,8 +1166,6 @@ SISResetVideo(ScrnInfoPtr pScrn) /* Select RGB chroma key format */ if(pSiS->VGAEngine == SIS_300_VGA) { setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x40); - } else { - /* setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x01, 0x01); */ } /* Reset scale control and contrast */ @@ -895,10 +1181,18 @@ SISResetVideo(ScrnInfoPtr pScrn) setvideoreg(pSiS, Index_VI_Play_Threshold_Low, 0x00); setvideoreg(pSiS, Index_VI_Play_Threshold_High, 0x00); - if((pSiS->Chipset == PCI_CHIP_SIS330) || (pSiS->Chipset == PCI_CHIP_SIS660)) { - /* What does this do? */ + if(pSiS->Chipset == PCI_CHIP_SIS330) { setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x00, 0x10); + } else if(pSiS->Chipset == PCI_CHIP_SIS660) { + setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x00, 0xE0); + } + if(pSiS->sishw_ext.jChipType == SIS_661) { + setvideoregmask(pSiS, Index_VI_V_Buf_Start_Over, 0x24, 0x3c); } + + 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) -------------------------- */ @@ -912,13 +1206,18 @@ SISResetVideo(ScrnInfoPtr pScrn) /* set default properties for overlay 2(CRT2) -------------------------- */ if(pPriv->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); - } + 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); } } @@ -940,27 +1239,27 @@ set_dispmode(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) 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 */ + 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 + 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 */ - } + if(pSiS->VBFlags & DISPTYPE_DISP1) { + pPriv->displayMode = DISPMODE_SINGLE1; /* CRT1 only */ + } else { + pPriv->displayMode = DISPMODE_SINGLE2; /* CRT2 only */ + } } } @@ -977,22 +1276,22 @@ set_disptype_regs(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) /* * SR06[7:6] - * Bit 7: Enable overlay 2 on CRT2 - * Bit 6: Enable overlay 1 on CRT2 + * Bit 7: Enable overlay 1 on CRT2 + * Bit 6: Enable overlay 0 on CRT2 * SR32[7:6] - * Bit 7: DCLK/TCLK overlay 2 + * Bit 7: DCLK/TCLK overlay 1 * 0=DCLK (overlay on CRT1) * 1=TCLK (overlay on CRT2) - * Bit 6: DCLK/TCLK overlay 1 + * 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 1 for CRT1 and - * overlay 2 for CRT2. + * 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 1 on CRT2 if in SINGLE2 mode. + * 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 @@ -1008,7 +1307,7 @@ set_disptype_regs(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) case DISPMODE_SINGLE1: /* CRT1-only mode: */ if(pPriv->hasTwoOverlays) { if(pPriv->dualHeadMode) { - setsrregmask(pSiS, 0x06, 0x00, 0x40); /* overlay 1 -> CRT1 */ + setsrregmask(pSiS, 0x06, 0x00, 0x40); /* overlay 0 -> CRT1 */ setsrregmask(pSiS, 0x32, 0x00, 0x40); } else { setsrregmask(pSiS, 0x06, 0x00, 0xc0); /* both overlays -> CRT1 */ @@ -1029,10 +1328,10 @@ set_disptype_regs(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) case DISPMODE_SINGLE2: /* CRT2-only mode: */ if(pPriv->hasTwoOverlays) { if(pPriv->dualHeadMode) { - setsrregmask(pSiS, 0x06, 0x80, 0x80); /* overlay 2 -> CRT2 */ + setsrregmask(pSiS, 0x06, 0x80, 0x80); /* overlay 1 -> CRT2 */ setsrregmask(pSiS, 0x32, 0x80, 0x80); } else { - setsrregmask(pSiS, 0x06, 0x40, 0xc0); /* overlay 1 -> CRT2 */ + setsrregmask(pSiS, 0x06, 0x40, 0xc0); /* overlay 0 -> CRT2 */ setsrregmask(pSiS, 0x32, 0xc0, 0xc0); /* (although both clocks for CRT2!) */ } } else { @@ -1049,7 +1348,7 @@ set_disptype_regs(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) case DISPMODE_MIRROR: /* CRT1+CRT2-mode: (only on chips with 2 overlays) */ default: - setsrregmask(pSiS, 0x06, 0x80, 0xc0); /* overlay 1 -> CRT1, overlay 2 -> CRT2 */ + setsrregmask(pSiS, 0x06, 0x80, 0xc0); /* overlay 0 -> CRT1, overlay 1 -> CRT2 */ setsrregmask(pSiS, 0x32, 0x80, 0xc0); break; } @@ -1083,22 +1382,37 @@ set_maxencoding(SISPtr pSiS, SISPortPrivPtr pPriv) } else { DummyEncoding.width = IMAGE_MAX_WIDTH_315; DummyEncoding.height = IMAGE_MAX_HEIGHT_315; + if(pSiS->Chipset == PCI_CHIP_SIS340) { + DummyEncoding.width = IMAGE_MAX_WIDTH_340; + } if(pPriv->hasTwoOverlays) { /* Only half width available if both overlays * are going to be used */ #ifdef SISDUALHEAD if(pSiS->DualHeadMode) { - DummyEncoding.width >>= 1; + if(pSiS->Chipset == PCI_CHIP_SIS660) { + DummyEncoding.width = 1536; + } else { + DummyEncoding.width >>= 1; + } } else #endif #ifdef SISMERGED if(pSiS->MergedFB) { - DummyEncoding.width >>= 1; + if(pSiS->Chipset == PCI_CHIP_SIS660) { + DummyEncoding.width = 1536; + } else { + DummyEncoding.width >>= 1; + } } else #endif if(pPriv->displayMode == DISPMODE_MIRROR) { - DummyEncoding.width >>= 1; + if(pSiS->Chipset == PCI_CHIP_SIS660) { + DummyEncoding.width = 1536; + } else { + DummyEncoding.width >>= 1; + } } } } @@ -1112,6 +1426,13 @@ SISSetupImageVideo(ScreenPtr pScreen) 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)))) @@ -1184,9 +1505,14 @@ SISSetupImageVideo(ScreenPtr pScreen) pPriv->grabbedByV4L= FALSE; pPriv->NoOverlay = FALSE; pPriv->PrevOverlay = FALSE; + pPriv->is340 = (pSiS->Chipset == PCI_CHIP_SIS340) ? TRUE : FALSE; /* gotta uninit this someplace */ - REGION_INIT(pScreen, &pPriv->clip, NullBox, 0); +#if defined(REGION_NULL) + REGION_NULL(pScreen, &pPriv->clip); +#else + REGION_INIT(pScreen, &pPriv->clip, NullBox, 0); +#endif pSiS->adaptor = adapt; @@ -1202,6 +1528,9 @@ SISSetupImageVideo(ScreenPtr pScreen) 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); @@ -1220,6 +1549,7 @@ SISSetupImageVideo(ScreenPtr pScreen) 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); @@ -1243,12 +1573,22 @@ SISSetupImageVideo(ScreenPtr pScreen) 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_SHC = MAKE_ATOM(sisxvsdhidehwcursor); + pSiS->xv_PMD = MAKE_ATOM(sisxvsdpanelmode); +#ifdef TWDEBUG + pSiS->xv_STR = MAKE_ATOM(sisxvsetreg); +#endif #ifdef SIS_CP SIS_CP_VIDEO_ATOMS #endif - pSiS->xv_sisdirectunlocked = FALSE; + pSiS->xv_sisdirectunlocked = 0; pSiS->xv_sd_result = 0; /* 300 series require double words for addresses and pitches, @@ -1271,13 +1611,14 @@ SISSetupImageVideo(ScreenPtr pScreen) * 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 ? ? - * 630/730 2 ? ? + * 300 2 ? 720x576 + * 630/730 2 ? 720x576 * 315 2 960? 1920x1080 * 650/740 2 960 ("120x128") 1920x1080 * M650/651.. 4 480 1920x1080 - * 330 2 960? 1920x1080? - * 660 ? ? ? + * 330 2 960 1920x1080 + * 661/741/760 4 768 1920x1080 + * 340 2 1280? ? * 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). @@ -1287,10 +1628,13 @@ SISSetupImageVideo(ScreenPtr pScreen) * 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. + * maximum width, or 1536 on 661/741/760. */ pPriv->linebufMergeLimit = LINEBUFLIMIT1; + if(pSiS->Chipset == PCI_CHIP_SIS660) { + pPriv->linebufMergeLimit = LINEBUFLIMIT3; + } set_maxencoding(pSiS, pPriv); @@ -1303,6 +1647,9 @@ SISSetupImageVideo(ScreenPtr pScreen) * generally larger, so our merging-limit is higher, too. */ pPriv->linebufMergeLimit = LINEBUFLIMIT2; + if(pSiS->Chipset == PCI_CHIP_SIS340) { + pPriv->linebufMergeLimit = LINEBUFLIMIT4; + } } } @@ -1313,11 +1660,15 @@ SISSetupImageVideo(ScreenPtr pScreen) set_disptype_regs(pScrn, pPriv); SISResetVideo(pScrn); + pSiS->ResetXv = SISResetVideo; + if(pSiS->VGAEngine == SIS_315_VGA) { + pSiS->ResetXvGamma = SISResetXvGamma; + } return adapt; } -#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,3,99,0,0) +#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,3,99,3,0) static Bool RegionsEqual(RegionPtr A, RegionPtr B) { @@ -1432,16 +1783,22 @@ SISSetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, } else if(attribute == pSiS->xvChromaMax) { pPriv->chromamax = value; } else if(attribute == pSiS->xv_USD) { - if((pSiS->enablesisctrl) && (value == SIS_DIRECTKEY)) - pSiS->xv_sisdirectunlocked = TRUE; - else - pSiS->xv_sisdirectunlocked = FALSE; + if(pSiS->enablesisctrl) { + if(value == SIS_DIRECTKEY) { + pSiS->xv_sisdirectunlocked++; + } else if(pSiS->xv_sisdirectunlocked) { + pSiS->xv_sisdirectunlocked--; + } + } else { + pSiS->xv_sisdirectunlocked = 0; + } } else if(attribute == pSiS->xv_SVF) { #ifdef SISDUALHEAD if(!pPriv->dualHeadMode) #endif if(pSiS->xv_sisdirectunlocked) { SISSwitchCRT2Type(pScrn, (unsigned long)value); + set_dispmode(pScrn, pPriv); set_allowswitchcrt(pSiS, pPriv); set_maxencoding(pSiS, pPriv); } @@ -1451,9 +1808,17 @@ SISSetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, #endif if(pSiS->xv_sisdirectunlocked) { SISSwitchCRT1Status(pScrn, (unsigned long)value); + set_dispmode(pScrn, pPriv); set_allowswitchcrt(pSiS, pPriv); set_maxencoding(pSiS, pPriv); } + } else if(attribute == pSiS->xv_RDT) { +#ifdef SISDUALHEAD + if(!pPriv->dualHeadMode) +#endif + if(pSiS->xv_sisdirectunlocked) { + SISRedetectCRT2Devices(pScrn); + } } else if(attribute == pSiS->xv_TAF) { if(pSiS->xv_sisdirectunlocked) { SiS_SetSISTVantiflicker(pScrn, (int)value); @@ -1516,26 +1881,30 @@ SISSetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, } } else if(attribute == pSiS->xv_CMD) { if(pSiS->xv_sisdirectunlocked) { + int result = 0; pSiS->xv_sd_result = (value & 0xffffff00); - if(SISCheckModeIndexForCRT2Type(pScrn, (unsigned short)(value & 0xff), - (unsigned short)((value >> 8) & 0xff), - FALSE)) { - pSiS->xv_sd_result |= 0x01; - } + result = SISCheckModeIndexForCRT2Type(pScrn, (unsigned short)(value & 0xff), + (unsigned short)((value >> 8) & 0xff), + FALSE); + pSiS->xv_sd_result |= (result & 0xff); } } else if(attribute == pSiS->xv_SGA) { if(pSiS->xv_sisdirectunlocked) { + Bool backup = pSiS->XvGamma; + pSiS->CRT1gamma = (value & 0x01) ? TRUE : FALSE; + pSiS->CRT2gamma = (value & 0x02) ? TRUE : FALSE; + pSiS->XvGamma = (value & 0x04) ? TRUE : FALSE; #ifdef SISDUALHEAD if(pPriv->dualHeadMode) { - pSiSEnt->CRT1gamma = (value & 0x01) ? TRUE : FALSE; - pSiSEnt->CRT2gamma = (value & 0x02) ? TRUE : FALSE; - } else { -#endif - pSiS->CRT1gamma = (value & 0x01) ? TRUE : FALSE; - pSiS->CRT2gamma = (value & 0x02) ? TRUE : FALSE; -#ifdef SISDUALHEAD + pSiSEnt->CRT1gamma = pSiS->CRT1gamma; + pSiSEnt->CRT2gamma = pSiS->CRT2gamma; } #endif + if(pSiS->VGAEngine == SIS_315_VGA) { + if(backup != pSiS->XvGamma) { + SiSUpdateXvGamma(pSiS, pPriv); + } + } } } else if(attribute == pSiS->xv_TXS) { if((value < -16) || (value > 16)) @@ -1585,6 +1954,54 @@ SISSetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, if(pSiS->xv_sisdirectunlocked) { pSiS->GammaPBriB = value; } + } else if(attribute == pSiS->xv_BRR2) { + if((value < 100) || (value > 10000)) + return BadValue; + if(pSiS->xv_sisdirectunlocked) { +#ifdef SISDUALHEAD + if(pPriv->dualHeadMode) pSiSEnt->GammaBriR = value; +#endif + } + } else if(attribute == pSiS->xv_BRG2) { + if((value < 100) || (value > 10000)) + return BadValue; + if(pSiS->xv_sisdirectunlocked) { +#ifdef SISDUALHEAD + if(pPriv->dualHeadMode) pSiSEnt->GammaBriG = value; +#endif + } + } else if(attribute == pSiS->xv_BRB2) { + if((value < 100) || (value > 10000)) + return BadValue; + if(pSiS->xv_sisdirectunlocked) { +#ifdef SISDUALHEAD + if(pPriv->dualHeadMode) pSiSEnt->GammaBriB = value; +#endif + } + } else if(attribute == pSiS->xv_PBR2) { + if((value < 100) || (value > 10000)) + return BadValue; + if(pSiS->xv_sisdirectunlocked) { +#ifdef SISDUALHEAD + if(pPriv->dualHeadMode) pSiSEnt->GammaPBriR = value; +#endif + } + } else if(attribute == pSiS->xv_PBG2) { + if((value < 100) || (value > 10000)) + return BadValue; + if(pSiS->xv_sisdirectunlocked) { +#ifdef SISDUALHEAD + if(pPriv->dualHeadMode) pSiSEnt->GammaPBriG = value; +#endif + } + } else if(attribute == pSiS->xv_PBB2) { + if((value < 100) || (value > 10000)) + return BadValue; + if(pSiS->xv_sisdirectunlocked) { +#ifdef SISDUALHEAD + if(pPriv->dualHeadMode) pSiSEnt->GammaPBriB = value; +#endif + } } else if(attribute == pSiS->xv_SHC) { if(pSiS->xv_sisdirectunlocked) { Bool VisibleBackup = pSiS->HWCursorIsVisible; @@ -1600,6 +2017,35 @@ SISSetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, pSiS->HWCursorIsVisible = VisibleBackup; } } + } else if(attribute == pSiS->xv_PMD) { + if(pSiS->xv_sisdirectunlocked) { + if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTSCALE) { + if(value & 0x01) pSiS->SiS_Pr->UsePanelScaler = -1; + else if(value & 0x02) pSiS->SiS_Pr->UsePanelScaler = 1; + else pSiS->SiS_Pr->UsePanelScaler = 0; + if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTCENTER) { + if(value & 0x04) pSiS->SiS_Pr->CenterScreen = -1; + else if(value & 0x08) pSiS->SiS_Pr->CenterScreen = 1; + else pSiS->SiS_Pr->CenterScreen = 0; + } + } + } +#ifdef TWDEBUG + } else if(attribute == pSiS->xv_STR) { + unsigned short port; + switch((value & 0xff000000) >> 24) { + case 0x00: port = SISSR; break; + case 0x01: port = SISPART1; break; + case 0x02: port = SISPART2; break; + case 0x03: port = SISPART3; break; + case 0x04: port = SISPART4; break; + case 0x05: port = SISCR; break; + case 0x06: port = SISVID; break; + default: return BadValue; + } + outSISIDXREG(port,((value & 0x00ff0000) >> 16), ((value & 0x0000ff00) >> 8)); + return Success; +#endif #ifdef SIS_CP SIS_CP_VIDEO_SETATTRIBUTE #endif @@ -1615,20 +2061,35 @@ SISSetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, } } else if(attribute == pSiS->xvHue) { if((value < -8) || (value > 7)) - return BadValue; + return BadValue; pPriv->hue = value; } else if(attribute == pSiS->xvSaturation) { if((value < -7) || (value > 7)) - return BadValue; + return BadValue; pPriv->saturation = value; + } else if(attribute == pSiS->xvGammaRed) { + if((value < 100) || (value > 10000)) + return BadValue; + pSiS->XvGammaRed = value; + SiSUpdateXvGamma(pSiS, pPriv); + } else if(attribute == pSiS->xvGammaGreen) { + if((value < 100) || (value > 10000)) + return BadValue; + pSiS->XvGammaGreen = value; + SiSUpdateXvGamma(pSiS, pPriv); + } else if(attribute == pSiS->xvGammaBlue) { + if((value < 100) || (value > 10000)) + return BadValue; + pSiS->XvGammaBlue = value; + SiSUpdateXvGamma(pSiS, pPriv); } else return BadMatch; } else return BadMatch; return Success; } -static int +static int SISGetPortAttribute( - ScrnInfoPtr pScrn, + ScrnInfoPtr pScrn, Atom attribute, INT32 *value, pointer data @@ -1637,7 +2098,7 @@ SISGetPortAttribute( SISPtr pSiS = SISPTR(pScrn); #ifdef SISDUALHEAD SISEntPtr pSiSEnt = pSiS->entityPrivate;; -#endif +#endif if(attribute == pSiS->xvBrightness) { *value = pPriv->brightness; @@ -1684,7 +2145,7 @@ SISGetPortAttribute( } else if(attribute == pSiS->xv_GSF) { *value = pSiS->SiS_SD_Flags; } else if(attribute == pSiS->xv_USD) { - *value = pSiS->xv_sisdirectunlocked ? 1 : 0; + *value = pSiS->xv_sisdirectunlocked; } else if(attribute == pSiS->xv_TAF) { *value = SiS_GetSISTVantiflicker(pScrn); } else if(attribute == pSiS->xv_TSA) { @@ -1712,6 +2173,7 @@ SISGetPortAttribute( } else if(attribute == pSiS->xv_CMDR) { *value = pSiS->xv_sd_result; } else if(attribute == pSiS->xv_OVR) { + /* Changing of CRT2 settings not supported in DHM! */ *value = 0; if(pSiS->OptTVSOver == 1) *value = 3; else if(pSiS->UseCHOverScan == 1) *value = 2; @@ -1728,6 +2190,7 @@ SISGetPortAttribute( if(pSiS->CRT2gamma) *value |= 0x02; #ifdef SISDUALHEAD } + if(pSiS->XvGamma) *value |= 0x04; #endif } else if(attribute == pSiS->xv_TXS) { *value = SiS_GetTVxscale(pScrn); @@ -1747,8 +2210,58 @@ SISGetPortAttribute( *value = pSiS->GammaPBriG; } else if(attribute == pSiS->xv_PBB) { *value = pSiS->GammaPBriB; + } else if(attribute == pSiS->xv_BRR2) { +#ifdef SISDUALHEAD + if(pPriv->dualHeadMode) *value = pSiSEnt->GammaBriR; + else +#endif + *value = pSiS->GammaBriR; + } else if(attribute == pSiS->xv_BRG2) { +#ifdef SISDUALHEAD + if(pPriv->dualHeadMode) *value = pSiSEnt->GammaBriG; + else +#endif + *value = pSiS->GammaBriG; + } else if(attribute == pSiS->xv_BRB2) { +#ifdef SISDUALHEAD + if(pPriv->dualHeadMode) *value = pSiSEnt->GammaBriB; + else +#endif + *value = pSiS->GammaBriB; + } else if(attribute == pSiS->xv_PBR2) { +#ifdef SISDUALHEAD + if(pPriv->dualHeadMode) *value = pSiSEnt->GammaPBriR; + else +#endif + *value = pSiS->GammaPBriR; + } else if(attribute == pSiS->xv_PBG2) { +#ifdef SISDUALHEAD + if(pPriv->dualHeadMode) *value = pSiSEnt->GammaPBriG; + else +#endif + *value = pSiS->GammaPBriG; + } else if(attribute == pSiS->xv_PBB2) { +#ifdef SISDUALHEAD + if(pPriv->dualHeadMode) *value = pSiSEnt->GammaPBriB; + else +#endif + *value = pSiS->GammaPBriB; } else if(attribute == pSiS->xv_SHC) { *value = pSiS->HideHWCursor ? 1 : 0; + } else if(attribute == pSiS->xv_PMD) { + *value = 0; + if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTSCALE) { + switch(pSiS->SiS_Pr->UsePanelScaler) { + case -1: *value |= 0x01; break; + case 1: *value |= 0x02; break; + } + if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTCENTER) { + switch(pSiS->SiS_Pr->CenterScreen) { + case -1: *value |= 0x04; break; + case 1: *value |= 0x08; break; + } + } + } #ifdef SIS_CP SIS_CP_VIDEO_GETATTRIBUTE #endif @@ -1764,6 +2277,12 @@ SISGetPortAttribute( *value = pPriv->hue; } else if(attribute == pSiS->xvSaturation) { *value = pPriv->saturation; + } else if(attribute == pSiS->xvGammaRed) { + *value = pSiS->XvGammaRed; + } else if(attribute == pSiS->xvGammaGreen) { + *value = pSiS->XvGammaGreen; + } else if(attribute == pSiS->xvGammaBlue) { + *value = pSiS->XvGammaBlue; } else return BadMatch; } else return BadMatch; return Success; @@ -1795,12 +2314,10 @@ SiSHandleSiSDirectCommand(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv, sisdirectcomm break; case SDC_CMD_CHECKMODEFORCRT2: j = sdcbuf->sdc_parm[0]; - sdcbuf->sdc_parm[0] = 0; - if(SISCheckModeIndexForCRT2Type(pScrn, (unsigned short)(j & 0xff), - (unsigned short)((j >> 8) & 0xff), - FALSE)) { - sdcbuf->sdc_parm[0] = 1; - } + sdcbuf->sdc_parm[0] = SISCheckModeIndexForCRT2Type(pScrn, + (unsigned short)(j & 0xff), + (unsigned short)((j >> 8) & 0xff), + FALSE) & 0xff; break; default: sdcbuf->sdc_header = SDC_RESULT_UNDEFCMD; @@ -1840,16 +2357,17 @@ calc_scale_factor(SISOverlayPtr pOverlay, ScrnInfoPtr pScrn, int origdstH = dstH; int modeflags = pOverlay->currentmode->Flags; - /* TW: Stretch image due to panel link scaling */ - if(pSiS->VBFlags & CRT2_LCD) { + /* Stretch image due to panel link scaling */ + if(pSiS->VBFlags & (CRT2_LCD | CRT1_LCDA)) { if(pPriv->bridgeIsSlave) { if(pSiS->VBFlags & (VB_LVDS | VB_30xBDH)) { if(pSiS->MiscFlags & MISC_PANELLINKSCALER) { dstH = (dstH * LCDheight) / pOverlay->SCREENheight; } } - } else if(iscrt2) { - if(pSiS->VBFlags & (VB_LVDS | VB_30xBDH)) { + } else if((iscrt2 && (pSiS->VBFlags & CRT2_LCD)) || + (!iscrt2 && (pSiS->VBFlags & CRT1_LCDA))) { + if(pSiS->VBFlags & (VB_LVDS | VB_30xBDH | CRT1_LCDA)) { if(pSiS->MiscFlags & MISC_PANELLINKSCALER) { dstH = (dstH * LCDheight) / pOverlay->SCREENheight; if(pPriv->displayMode == DISPMODE_MIRROR) flag = 1; @@ -1863,99 +2381,94 @@ calc_scale_factor(SISOverlayPtr pOverlay, ScrnInfoPtr pScrn, * Interlace mode vice versa. */ if(modeflags & V_DBLSCAN) { - dstH = origdstH << 1; - flag = 0; - if((pSiS->sishw_ext.jChipType >= SIS_315H) && - (pSiS->sishw_ext.jChipType <= SIS_550)) { - dstW <<= 1; - } + dstH = origdstH << 1; + flag = 0; + if((pSiS->sishw_ext.jChipType >= SIS_315H) && + (pSiS->sishw_ext.jChipType <= SIS_550)) { + dstW <<= 1; + } } if(modeflags & V_INTERLACE) { - dstH = origdstH >> 1; - flag = 0; + dstH = origdstH >> 1; + flag = 0; } -#if 0 - /* TEST @@@ */ - if(pOverlay->bobEnable & 0x08) dstH <<= 1; -#endif - if(dstW < OVERLAY_MIN_WIDTH) dstW = OVERLAY_MIN_WIDTH; if(dstW == srcW) { - pOverlay->HUSF = 0x00; - pOverlay->IntBit = 0x05; - pOverlay->wHPre = 0; + pOverlay->HUSF = 0x00; + pOverlay->IntBit = 0x05; + pOverlay->wHPre = 0; } else if(dstW > srcW) { - dstW += 2; - pOverlay->HUSF = (srcW << 16) / dstW; - pOverlay->IntBit = 0x04; - pOverlay->wHPre = 0; + dstW += 2; + pOverlay->HUSF = (srcW << 16) / dstW; + pOverlay->IntBit = 0x04; + pOverlay->wHPre = 0; } 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; - } + int tmpW = dstW; - I = 0; - pOverlay->IntBit = 0x01; - while (srcW >= tmpW) { - tmpW <<= 1; - I++; - } - pOverlay->wHPre = (CARD8)(I - 1); - dstW <<= (I - 1); - if((srcW % dstW)) - pOverlay->HUSF = ((srcW - dstW) << 16) / dstW; - else - pOverlay->HUSF = 0x00; + /* 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); + if((srcW % dstW)) + pOverlay->HUSF = ((srcW - dstW) << 16) / dstW; + else + pOverlay->HUSF = 0x00; } if(dstH < OVERLAY_MIN_HEIGHT) dstH = OVERLAY_MIN_HEIGHT; if(dstH == srcH) { - pOverlay->VUSF = 0x00; - pOverlay->IntBit |= 0x0A; + pOverlay->VUSF = 0x00; + pOverlay->IntBit |= 0x0A; } else if(dstH > srcH) { - dstH += 0x02; - pOverlay->VUSF = (srcH << 16) / dstH; - pOverlay->IntBit |= 0x08; + dstH += 0x02; + pOverlay->VUSF = (srcH << 16) / dstH; + pOverlay->IntBit |= 0x08; } else { - CARD32 realI; - I = realI = srcH / dstH; - pOverlay->IntBit |= 0x02; + I = srcH / dstH; + pOverlay->IntBit |= 0x02; - if(I < 2) { - pOverlay->VUSF = ((srcH - dstH) << 16) / dstH; - /* TW: Needed for LCD-scaling modes */ - if((flag) && (mult = (srcH / origdstH)) >= 2) - pOverlay->pitch /= mult; - } else { + 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; - } + 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 = 0x00; - } - /* set video frame buffer offset */ - pOverlay->pitch = (CARD16)(srcPitch*I); + 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 = 0x00; } - } + /* set video frame buffer offset */ + pOverlay->pitch = (CARD16)(srcPitch * I); + } + } } #ifdef SISMERGED @@ -1990,196 +2503,193 @@ calc_scale_factor_2(SISOverlayPtr pOverlay, ScrnInfoPtr pScrn, * Interlace mode vice versa. */ if(modeflags & V_DBLSCAN) { - dstH = origdstH << 1; - flag = 0; - if((pSiS->sishw_ext.jChipType >= SIS_315H) && - (pSiS->sishw_ext.jChipType <= SIS_550)) { - dstW <<= 1; - } + dstH = origdstH << 1; + flag = 0; + if((pSiS->sishw_ext.jChipType >= SIS_315H) && + (pSiS->sishw_ext.jChipType <= SIS_550)) { + dstW <<= 1; + } } if(modeflags & V_INTERLACE) { - dstH = origdstH >> 1; - flag = 0; + dstH = origdstH >> 1; + flag = 0; } -#if 0 - /* TEST @@@ */ - if(pOverlay->bobEnable & 0x08) dstH <<= 1; -#endif - if(dstW < OVERLAY_MIN_WIDTH) dstW = OVERLAY_MIN_WIDTH; if(dstW == srcW) { - pOverlay->HUSF2 = 0x00; - pOverlay->IntBit2 = 0x05; - pOverlay->wHPre2 = 0; + pOverlay->HUSF2 = 0x00; + pOverlay->IntBit2 = 0x05; + pOverlay->wHPre2 = 0; } else if(dstW > srcW) { - dstW += 2; - pOverlay->HUSF2 = (srcW << 16) / dstW; - pOverlay->IntBit2 = 0x04; - pOverlay->wHPre2 = 0; + dstW += 2; + pOverlay->HUSF2 = (srcW << 16) / dstW; + pOverlay->IntBit2 = 0x04; + pOverlay->wHPre2 = 0; } 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; - } + int tmpW = dstW; - I = 0; - pOverlay->IntBit2 = 0x01; - while (srcW >= tmpW) { - tmpW <<= 1; - I++; - } - pOverlay->wHPre2 = (CARD8)(I - 1); - dstW <<= (I - 1); - if((srcW % dstW)) - pOverlay->HUSF2 = ((srcW - dstW) << 16) / dstW; - else - pOverlay->HUSF2 = 0x00; + /* 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); + 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; + pOverlay->VUSF2 = 0x00; + pOverlay->IntBit2 |= 0x0A; } else if(dstH > srcH) { - dstH += 0x02; - pOverlay->VUSF2 = (srcH << 16) / dstH; - pOverlay->IntBit2 |= 0x08; + dstH += 0x02; + pOverlay->VUSF2 = (srcH << 16) / dstH; + pOverlay->IntBit2 |= 0x08; } else { - CARD32 realI; - I = realI = srcH / dstH; - pOverlay->IntBit2 |= 0x02; + 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(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; - } + 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); + 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 -static CARD8 -calc_line_buf_size(CARD32 srcW, CARD8 wHPre, CARD32 pixelFormat) +static CARD16 +calc_line_buf_size(CARD32 srcW, CARD8 wHPre, CARD8 planar, SISPortPrivPtr pPriv) { - CARD8 preHIDF; CARD32 I; - CARD32 line = srcW; - if( (pixelFormat == PIXEL_FMT_YV12) || - (pixelFormat == PIXEL_FMT_I420) || - (pixelFormat == PIXEL_FMT_NV12) || - (pixelFormat == PIXEL_FMT_NV21) ) - { - preHIDF = wHPre & 0x07; - switch (preHIDF) - { - case 3 : - if((line & 0xffffff00) == line) - I = (line >> 8); - else - I = (line >> 8) + 1; - return((CARD8)(I * 32 - 1)); - case 4 : - if((line & 0xfffffe00) == line) - I = (line >> 9); - else - I = (line >> 9) + 1; - return((CARD8)(I * 64 - 1)); - case 5 : - if((line & 0xfffffc00) == line) - I = (line >> 10); - else - I = (line >> 10) + 1; - return((CARD8)(I * 128 - 1)); - case 6 : - return((CARD8)(255)); - default : - if((line & 0xffffff80) == line) - I = (line >> 7); - else - I = (line >> 7) + 1; - return((CARD8)(I * 16 - 1)); + if(planar) { + + switch(wHPre & 0x07) { + case 3: + I = (srcW >> 8); + if(srcW & 0xff) I++; + I <<= 5; + break; + case 4: + I = (srcW >> 9); + if(srcW & 0x1ff) I++; + I <<= 6; + break; + case 5: + I = (srcW >> 10); + if(srcW & 0x3ff) I++; + I <<= 7; + break; + case 6: + if(pPriv->is340) { + I = (srcW >> 11); + if(srcW & 0x7ff) I++; + I <<= 8; + break; + } else { + return((CARD16)(255)); + } + default: + I = (srcW >> 7); + if(srcW & 0x7f) I++; + I <<= 4; + break; } - } else { /* YUV2, UYVY */ - if((line & 0xffffff8) == line) - I = (line >> 3); - else - I = (line >> 3) + 1; - return((CARD8)(I - 1)); + + } else { /* packed */ + + I = (srcW >> 3); + if(srcW & 0x07) I++; + } + + if(I <= 3) I = 4; + + return((CARD16)(I - 1)); } static __inline void -set_line_buf_size_1(SISOverlayPtr pOverlay) +calc_line_buf_size_1(SISOverlayPtr pOverlay, SISPortPrivPtr pPriv) { - pOverlay->lineBufSize = calc_line_buf_size(pOverlay->srcW,pOverlay->wHPre, pOverlay->pixelFormat); + pOverlay->lineBufSize = + calc_line_buf_size(pOverlay->srcW, pOverlay->wHPre, pOverlay->planar, pPriv); } #ifdef SISMERGED static __inline void -set_line_buf_size_2(SISOverlayPtr pOverlay) +calc_line_buf_size_2(SISOverlayPtr pOverlay, SISPortPrivPtr pPriv) { - pOverlay->lineBufSize2 = calc_line_buf_size(pOverlay->srcW2,pOverlay->wHPre2, pOverlay->pixelFormat); + pOverlay->lineBufSize2 = + calc_line_buf_size(pOverlay->srcW2, pOverlay->wHPre2, pOverlay->planar, pPriv); } static void merge_line_buf_mfb(SISPtr pSiS, SISPortPrivPtr pPriv, Bool enable1, Bool enable2, short width1, short width2, short limit) { - unsigned char misc1, misc2, mask = pPriv->linebufmask; + unsigned char misc1, misc2, mask = pPriv->linebufmask; - if(pPriv->hasTwoOverlays) { /* This means we are in MIRROR mode */ + 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 = 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); + 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 */ + } else { /* This means we are either in SINGLE1 or SINGLE2 mode */ - misc2 = 0x00; - if(enable1 || enable2) misc1 = 0x04; - else misc1 = 0x00; + misc2 = 0x00; + if(enable1 || enable2) misc1 = 0x04; + else misc1 = 0x00; - setvideoregmask(pSiS, Index_VI_Control_Misc2, misc2, mask); - setvideoregmask(pSiS, Index_VI_Control_Misc1, misc1, 0x04); + setvideoregmask(pSiS, Index_VI_Control_Misc2, misc2, mask); + setvideoregmask(pSiS, Index_VI_Control_Misc1, misc1, 0x04); - } + } } #endif @@ -2207,6 +2717,7 @@ merge_line_buf_mfb(SISPtr pSiS, SISPortPrivPtr pPriv, Bool enable1, Bool enable2 * 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. * */ @@ -2413,12 +2924,12 @@ set_brightness(SISPtr pSiS, CARD8 brightness) static __inline void set_contrast(SISPtr pSiS, CARD8 contrast) { - setvideoregmask(pSiS, Index_VI_Contrast_Enh_Ctrl, contrast ^ 0x07, 0x07); + setvideoregmask(pSiS, Index_VI_Contrast_Enh_Ctrl, contrast, 0x07); } /* 315 series and later only */ static __inline void -set_saturation(SISPtr pSiS, char saturation) +set_saturation(SISPtr pSiS, short saturation) { CARD8 temp = 0; @@ -2436,15 +2947,17 @@ set_saturation(SISPtr pSiS, char saturation) static __inline void set_hue(SISPtr pSiS, CARD8 hue) { - setvideoreg(pSiS, Index_VI_Hue, (hue & 0x08) ? (hue ^ 0x07) : 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 or 65x (x>0) */ + /* This is not supported on M65x, 65x (x>0) or later */ /* For CRT1 ONLY!!! */ - if(!(pSiS->ChipFlags & SiSCF_Is65x)) { + if((!(pSiS->ChipFlags & SiSCF_Is65x)) && + (pSiS->Chipset != PCI_CHIP_SIS660) && + (pSiS->Chipset != PCI_CHIP_SIS340)) { setvideoregmask(pSiS, Index_VI_Control_Misc2, mybool ? 0x04 : 0x00, 0x04); if(mybool) pOverlay->keyOP = VI_ROP_Always; } @@ -2464,16 +2977,11 @@ set_disablegfxlr(SISPtr pSiS, Bool mybool, SISOverlayPtr pOverlay) static void set_overlay(SISPtr pSiS, SISOverlayPtr pOverlay, SISPortPrivPtr pPriv, int index, int iscrt2) { - ScrnInfoPtr pScrn = pSiS->pScrn; - - CARD16 pitch=0; CARD8 h_over=0, v_over=0; - CARD16 top, bottom, left, right; + CARD16 top, bottom, left, right, pitch=0; CARD16 screenX, screenY; - int modeflags; - CARD8 data; - CARD32 watchdog; CARD32 PSY; + int modeflags, watchdog=0; #ifdef SISMERGED if(pSiS->MergedFB && iscrt2) { @@ -2522,34 +3030,62 @@ set_overlay(SISPtr pSiS, SISOverlayPtr pOverlay, SISPortPrivPtr pPriv, int index /* set line buffer size */ #ifdef SISMERGED - if(pSiS->MergedFB && iscrt2) - setvideoreg(pSiS, Index_VI_Line_Buffer_Size, pOverlay->lineBufSize2); - else + if(pSiS->MergedFB && iscrt2) { + setvideoreg(pSiS, Index_VI_Line_Buffer_Size, (CARD8)pOverlay->lineBufSize2); + if(pPriv->is340) { + setvideoreg(pSiS, Index_VI_Line_Buffer_Size_High, (CARD8)(pOverlay->lineBufSize2 >> 8)); + } + } else { #endif - setvideoreg(pSiS, Index_VI_Line_Buffer_Size, pOverlay->lineBufSize); + setvideoreg(pSiS, Index_VI_Line_Buffer_Size, (CARD8)pOverlay->lineBufSize); + if(pPriv->is340) { + 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) { - watchdog = WATCHDOG_DELAY; - while (pOverlay->VBlankActiveFunc(pSiS) && --watchdog); - watchdog = WATCHDOG_DELAY; - while ((!pOverlay->VBlankActiveFunc(pSiS)) && --watchdog); - if(!watchdog) xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Xv: Waiting for vertical retrace timed-out\n"); + 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 */ - data = getvideoreg(pSiS, Index_VI_Control_Misc1); - setvideoreg(pSiS, Index_VI_Control_Misc1, data | 0x20); - /* Is this required? */ - setvideoreg(pSiS, Index_VI_Control_Misc1, data | 0x20); + 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); - /* Is this required? (seems so) */ - if(pSiS->Chipset == SIS_315_VGA) - setvideoregmask(pSiS, Index_VI_Control_Misc3, 0x00, (1 << index)); + 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); /* Set Y buf pitch */ setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Pitch_Low, (CARD8)(pitch)); @@ -2569,95 +3105,85 @@ set_overlay(SISPtr pSiS, SISOverlayPtr pOverlay, SISPortPrivPtr pPriv, int index /* 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)); + 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->pixelFormat == PIXEL_FMT_YV12) || - (pOverlay->pixelFormat == PIXEL_FMT_I420) || - (pOverlay->pixelFormat == PIXEL_FMT_NV12) || - (pOverlay->pixelFormat == PIXEL_FMT_NV21) ) { + if(pOverlay->planar) { - CARD32 PSU=0, PSV=0, uvpitch = pitch; + CARD32 PSU = pOverlay->PSU; + CARD32 PSV = pOverlay->PSV; - PSU = pOverlay->PSU; - PSV = pOverlay->PSV; #ifdef SISMERGED if(pSiS->MergedFB && iscrt2) { PSU = pOverlay->PSU2; PSV = pOverlay->PSV2; } #endif - if((pOverlay->pixelFormat == PIXEL_FMT_YV12) || - (pOverlay->pixelFormat == PIXEL_FMT_I420)) { - uvpitch >>= 1; - } + + if(pOverlay->planar_shiftpitch) pitch >>= 1; /* Set U/V pitch */ - setvideoreg (pSiS, Index_VI_Disp_UV_Buf_Pitch_Low, (CARD8)uvpitch); - setvideoregmask (pSiS, Index_VI_Disp_Y_UV_Buf_Pitch_Middle, (CARD8)(uvpitch >> 4), 0xf0); + 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_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)); + 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)(uvpitch >> 12)); - setvideoreg (pSiS, Index_VI_U_Buf_Start_Over, ((CARD8)(PSU >> 24) & 0x03)); - setvideoreg (pSiS, Index_VI_V_Buf_Start_Over, ((CARD8)(PSV >> 24) & 0x03)); + 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(pSiS->sishw_ext.jChipType == SIS_661) { + 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)); + 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); + setvideoregmask(pSiS, Index_VI_Scale_Control, (pOverlay->IntBit2 << 3) | + (pOverlay->wHPre2), 0x7f); } 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)); + 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); + setvideoregmask(pSiS, Index_VI_Scale_Control, (pOverlay->IntBit << 3) | + (pOverlay->wHPre), 0x7f); #ifdef SISMERGED } #endif - - /* 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); - - setvideoregmask(pSiS, Index_VI_Control_Misc1, pOverlay->bobEnable, 0x1a); - - /* Lock the address registers */ - setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x20); + } /* Overlay MUST NOT be switched off while beam is over it */ static void close_overlay(SISPtr pSiS, SISPortPrivPtr pPriv) { - CARD32 watchdog; + int watchdog; if(!(pPriv->overlayStatus)) return; pPriv->overlayStatus = FALSE; @@ -2691,15 +3217,16 @@ close_overlay(SISPtr pSiS, SISPortPrivPtr pPriv) } setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x01); + watchdog = WATCHDOG_DELAY; - while(vblank_active_CRT2(pSiS) && --watchdog); + while((!vblank_active_CRT2(pSiS, pPriv)) && --watchdog); watchdog = WATCHDOG_DELAY; - while((!vblank_active_CRT2(pSiS)) && --watchdog); + while(vblank_active_CRT2(pSiS, pPriv) && --watchdog); setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02); watchdog = WATCHDOG_DELAY; - while(vblank_active_CRT2(pSiS) && --watchdog); + while((!vblank_active_CRT2(pSiS, pPriv)) && --watchdog); watchdog = WATCHDOG_DELAY; - while((!vblank_active_CRT2(pSiS)) && --watchdog); + while(vblank_active_CRT2(pSiS, pPriv) && --watchdog); #ifdef SIS_CP SIS_CP_RESET_CP @@ -2720,17 +3247,19 @@ close_overlay(SISPtr pSiS, SISPortPrivPtr pPriv) } } #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) && --watchdog); + while((!vblank_active_CRT1(pSiS, pPriv)) && --watchdog); watchdog = WATCHDOG_DELAY; - while((!vblank_active_CRT1(pSiS)) && --watchdog); + while(vblank_active_CRT1(pSiS, pPriv) && --watchdog); setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02); watchdog = WATCHDOG_DELAY; - while(vblank_active_CRT1(pSiS) && --watchdog); + while((!vblank_active_CRT1(pSiS, pPriv)) && --watchdog); watchdog = WATCHDOG_DELAY; - while((!vblank_active_CRT1(pSiS)) && --watchdog); + while(vblank_active_CRT1(pSiS, pPriv) && --watchdog); } } @@ -2751,10 +3280,9 @@ SISDisplayVideo(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) int index = 0, iscrt2 = 0; #ifdef SISMERGED unsigned char temp; - CARD32 watchdog; unsigned short screen2width=0; int srcOffsetX2=0, srcOffsetY2=0; - int sx2=0, sy2=0; + int sx2=0, sy2=0, watchdog; #endif pPriv->NoOverlay = FALSE; @@ -2786,15 +3314,21 @@ SISDisplayVideo(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) set_dispmode(pScrn, pPriv); /* Check if overlay is supported with current mode */ - if(pPriv->displayMode & (DISPMODE_SINGLE1 | DISPMODE_MIRROR)) { - if(!(pSiS->MiscFlags & MISC_CRT1OVERLAY)) { - if(pPriv->overlayStatus) { - close_overlay(pSiS, pPriv); - } - pPriv->NoOverlay = TRUE; - return; +#ifdef SISMERGED + if(!pSiS->MergedFB) { +#endif + if(pPriv->displayMode & (DISPMODE_SINGLE1 | DISPMODE_MIRROR)) { + if(!(pSiS->MiscFlags & MISC_CRT1OVERLAY)) { + if(pPriv->overlayStatus) { + close_overlay(pSiS, pPriv); + } + pPriv->NoOverlay = TRUE; + return; + } } +#ifdef SISMERGED } +#endif memset(&overlay, 0, sizeof(overlay)); @@ -2839,12 +3373,16 @@ SISDisplayVideo(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) 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; + /* xf86DrvMsg(0, X_INFO, "DV(1): %d %d %d %d\n", + overlay.dstBox.x1,overlay.dstBox.x2,overlay.dstBox.y1,overlay.dstBox.y2); */ #ifdef SISMERGED } #endif - if((overlay.dstBox.x1 > overlay.dstBox.x2) || - (overlay.dstBox.y1 > overlay.dstBox.y2)) { + /* 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 @@ -2852,7 +3390,7 @@ SISDisplayVideo(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) return; } - if((overlay.dstBox.x2 < 0) || (overlay.dstBox.y2 < 0)) { + if((overlay.dstBox.x2 <= 0) || (overlay.dstBox.y2 <= 0)) { #ifdef SISMERGED if(pSiS->MergedFB) overlay.DoFirst = FALSE; else @@ -2868,6 +3406,17 @@ SISDisplayVideo(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) 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; @@ -2876,14 +3425,20 @@ SISDisplayVideo(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) 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.x1 > overlay.dstBox2.x2) || - (overlay.dstBox2.y1 > overlay.dstBox2.y2)) - overlay.DoSecond = FALSE; - - if((overlay.dstBox2.x2 < 0) || (overlay.dstBox2.y2 < 0)) + if((overlay.dstBox2.x2 <= 0) || (overlay.dstBox2.y2 <= 0)) overlay.DoSecond = FALSE; if((overlay.dstBox2.x1 >= screen2width) || (overlay.dstBox2.y1 >= overlay.SCREENheight2)) @@ -2893,10 +3448,16 @@ SISDisplayVideo(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) 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; /* If neither overlay is to be displayed, disable them if they are currently enabled */ if((!overlay.DoFirst) && (!overlay.DoSecond)) { @@ -2906,19 +3467,19 @@ SISDisplayVideo(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) if(temp & 0x02) { watchdog = WATCHDOG_DELAY; if(pPriv->hasTwoOverlays) { - while(vblank_active_CRT1(pSiS) && --watchdog); + while((!vblank_active_CRT1(pSiS, pPriv)) && --watchdog); watchdog = WATCHDOG_DELAY; - while((!vblank_active_CRT1(pSiS)) && --watchdog); + while(vblank_active_CRT1(pSiS, pPriv) && --watchdog); } else { temp = getsrreg(pSiS, 0x06); if(!(temp & 0x40)) { - while(vblank_active_CRT1(pSiS) && --watchdog); + while((!vblank_active_CRT1(pSiS, pPriv)) && --watchdog); watchdog = WATCHDOG_DELAY; - while((!vblank_active_CRT1(pSiS)) && --watchdog); + while(vblank_active_CRT1(pSiS, pPriv) && --watchdog); } else { - while(vblank_active_CRT2(pSiS) && --watchdog); + while((!vblank_active_CRT2(pSiS, pPriv)) && --watchdog); watchdog = WATCHDOG_DELAY; - while((!vblank_active_CRT2(pSiS)) && --watchdog); + while(vblank_active_CRT2(pSiS, pPriv) && --watchdog); } } setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02); @@ -2929,9 +3490,9 @@ SISDisplayVideo(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) temp = getvideoreg(pSiS,Index_VI_Control_Misc0); if(temp & 0x02) { watchdog = WATCHDOG_DELAY; - while(vblank_active_CRT2(pSiS) && --watchdog); + while((!vblank_active_CRT2(pSiS, pPriv)) && --watchdog); watchdog = WATCHDOG_DELAY; - while((!vblank_active_CRT2(pSiS)) && --watchdog); + while(vblank_active_CRT2(pSiS, pPriv) && --watchdog); setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02); } } @@ -2941,13 +3502,11 @@ SISDisplayVideo(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) } #endif - /* xf86DrvMsg(0, X_INFO, "DV(2): %d %d %d %d | %d %d %d %d\n", - overlay.dstBox.x1,overlay.dstBox.x2,overlay.dstBox.y1,overlay.dstBox.y2, - overlay.dstBox2.x1,overlay.dstBox2.x2,overlay.dstBox2.y1,overlay.dstBox2.y2); */ - switch(pPriv->id) { case PIXEL_FMT_YV12: + overlay.planar = 1; + overlay.planar_shiftpitch = 1; #ifdef SISMERGED if((!pSiS->MergedFB) || (overlay.DoFirst)) { #endif @@ -2980,6 +3539,8 @@ SISDisplayVideo(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) break; case PIXEL_FMT_I420: + overlay.planar = 1; + overlay.planar_shiftpitch = 1; #ifdef SISMERGED if((!pSiS->MergedFB) || (overlay.DoFirst)) { #endif @@ -3013,6 +3574,8 @@ SISDisplayVideo(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) case PIXEL_FMT_NV12: case PIXEL_FMT_NV21: + overlay.planar = 1; + overlay.planar_shiftpitch = 0; #ifdef SISMERGED if((!pSiS->MergedFB) || (overlay.DoFirst)) { #endif @@ -3047,6 +3610,7 @@ SISDisplayVideo(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) case PIXEL_FMT_RGB6: case PIXEL_FMT_RGB5: default: + overlay.planar = 0; #ifdef SISMERGED if((!pSiS->MergedFB) || (overlay.DoFirst)) { #endif @@ -3108,9 +3672,9 @@ SISDisplayVideo(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) temp = getvideoreg(pSiS,Index_VI_Control_Misc0); if(temp & 0x02) { watchdog = WATCHDOG_DELAY; - while(vblank_active_CRT1(pSiS) && --watchdog); + while((!vblank_active_CRT1(pSiS, pPriv)) && --watchdog); watchdog = WATCHDOG_DELAY; - while((!vblank_active_CRT1(pSiS)) && --watchdog); + while(vblank_active_CRT1(pSiS, pPriv) && --watchdog); setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02); } } else if(!overlay.DoSecond) { @@ -3119,16 +3683,23 @@ SISDisplayVideo(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) temp = getvideoreg(pSiS,Index_VI_Control_Misc0); if(temp & 0x02) { watchdog = WATCHDOG_DELAY; - while(vblank_active_CRT2(pSiS) && --watchdog); + while((!vblank_active_CRT2(pSiS, pPriv)) && --watchdog); watchdog = WATCHDOG_DELAY; - while((!vblank_active_CRT2(pSiS)) && --watchdog); + while(vblank_active_CRT2(pSiS, pPriv) && --watchdog); setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02); } } } #endif + /* xf86DrvMsg(0, X_INFO, "DV(2): %d %d %d %d (%d %d) | %d %d %d %d (%d %d)\n", + overlay.dstBox.x1,overlay.dstBox.x2,overlay.dstBox.y1,overlay.dstBox.y2,srcOffsetX,srcOffsetY, + overlay.dstBox2.x1,overlay.dstBox2.x2,overlay.dstBox2.y1,overlay.dstBox2.y2,srcOffsetX2,srcOffsetY2); */ + /* 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) { @@ -3193,27 +3764,61 @@ SISDisplayVideo(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) #ifdef SISMERGED if((!pSiS->MergedFB) || (overlay.DoFirst)) #endif - set_line_buf_size_1(&overlay); + calc_line_buf_size_1(&overlay, pPriv); #ifdef SISMERGED if((pSiS->MergedFB) && (overlay.DoSecond)) - set_line_buf_size_2(&overlay); + 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 (not set!) scale factor */ + /* 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 video1 (used for CRT1/or CRT2) or video2 (used for CRT2) */ + + /* 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 */ + + /* set format (before color and chroma keys) */ set_format(pSiS, &overlay); /* set color key */ @@ -3236,35 +3841,10 @@ MIRROR: set_saturation(pSiS, pPriv->saturation); } - 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; - } - } - /* 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(!pPriv->hasTwoOverlays) { set_disablegfx(pSiS, FALSE, &overlay); @@ -3275,14 +3855,9 @@ MIRROR: SIS_CP_VIDEO_SET_CP #endif - /* set overlay parameters */ + /* set remaining overlay parameters */ set_overlay(pSiS, &overlay, pPriv, index, iscrt2); - - if(pSiS->VGAEngine == SIS_315_VGA) { - /* Trigger register copy for 315 series */ - setvideoregmask(pSiS, Index_VI_Control_Misc3, (1 << index), (1 << index)); - } - + /* enable overlay */ setvideoregmask (pSiS, Index_VI_Control_Misc0, 0x02, 0x02); @@ -3297,10 +3872,78 @@ MIRROR: 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 are 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; } @@ -3315,13 +3958,11 @@ SISAllocateOverlayMemory( FBLinearPtr new_linear; if(linear) { - if(linear->size >= size) - return linear; + if(linear->size >= size) return linear; - if(xf86ResizeOffscreenLinear(linear, size)) - return linear; + if(xf86ResizeOffscreenLinear(linear, size)) return linear; - xf86FreeOffscreenLinear(linear); + xf86FreeOffscreenLinear(linear); } pScreen = screenInfo.screens[pScrn->scrnIndex]; @@ -3330,25 +3971,25 @@ SISAllocateOverlayMemory( NULL, NULL, NULL); if(!new_linear) { - int max_size; + int max_size; - xf86QueryLargestOffscreenLinear(pScreen, &max_size, 8, + xf86QueryLargestOffscreenLinear(pScreen, &max_size, 8, PRIORITY_EXTREME); - if(max_size < size) return NULL; + if(max_size < size) return NULL; - xf86PurgeUnlockedOffscreenAreas(pScreen); - new_linear = xf86AllocateOffscreenLinear(pScreen, size, 8, + xf86PurgeUnlockedOffscreenAreas(pScreen); + new_linear = xf86AllocateOffscreenLinear(pScreen, size, 8, NULL, NULL, NULL); } if(!new_linear) - xf86DrvMsg(pScrn->scrnIndex, X_INFO, + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Xv: Failed to allocate %dK of video memory\n", size/1024); -#ifdef TWDEBUG +#ifdef TWDEBUG else - xf86DrvMsg(pScrn->scrnIndex, X_INFO, + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Xv: Allocated %dK of video memory\n", size/1024); -#endif +#endif return new_linear; } @@ -3359,8 +4000,8 @@ SISFreeOverlayMemory(ScrnInfoPtr pScrn) SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn); if(pPriv->linear) { - xf86FreeOffscreenLinear(pPriv->linear); - pPriv->linear = NULL; + xf86FreeOffscreenLinear(pPriv->linear); + pPriv->linear = NULL; } } @@ -3370,24 +4011,23 @@ SISStopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown) SISPortPrivPtr pPriv = (SISPortPrivPtr)data; SISPtr pSiS = SISPTR(pScrn); - if(pPriv->grabbedByV4L) - return; + 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; + close_overlay(pSiS, pPriv); + pPriv->mustwait = 1; } SISFreeOverlayMemory(pScrn); pPriv->videoStatus = 0; - pSiS->VideoTimerCallback = NULL; } else { if(pPriv->videoStatus & CLIENT_VIDEO_ON) { - pPriv->videoStatus = OFF_TIMER | CLIENT_VIDEO_ON; - pPriv->offTime = currentTime.milliseconds + OFF_DELAY; - pSiS->VideoTimerCallback = SISVideoTimerCallback; + UpdateCurrentTime(); + pPriv->offTime = currentTime.milliseconds + OFF_DELAY; + pPriv->videoStatus = OFF_TIMER | CLIENT_VIDEO_ON; + pSiS->VideoTimerCallback = SISVideoTimerCallback; } } } @@ -3406,6 +4046,7 @@ SISPutImage( ){ SISPtr pSiS = SISPTR(pScrn); SISPortPrivPtr pPriv = (SISPortPrivPtr)data; + XAAInfoRecPtr pXAA = pSiS->AccelInfoPtr; int totalSize=0; int depth = pSiS->CurrentLayout.bitsPerPixel >> 3; @@ -3417,8 +4058,7 @@ SISPutImage( } #endif - if(pPriv->grabbedByV4L) - return Success; + if(pPriv->grabbedByV4L) return Success; pPriv->drw_x = drw_x; pPriv->drw_y = drw_y; @@ -3455,6 +4095,14 @@ SISPutImage( 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){ @@ -3510,30 +4158,28 @@ SISPutImage( /* update cliplist */ if(pPriv->autopaintColorKey && (pPriv->grabbedByV4L || -#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,3,99,0,0) +#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) -#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,3,99,0,0) + if(!pPriv->grabbedByV4L) { REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes); -#else - REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes); -#endif + } /* draw these */ pPriv->PrevOverlay = pPriv->NoOverlay; - if((pPriv->NoOverlay) && (!pSiS->NoAccel)) { - XAAFillMono8x8PatternRects(pScrn, myreds[depth-1], 0x000000, GXcopy, ~0, + 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 { if(!pSiS->disablecolorkeycurrent) { -#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,3,99,0,0) - XAAFillSolidRects(pScrn, pPriv->colorKey, GXcopy, ~0, +#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 @@ -3624,48 +4270,9 @@ SISQueryImageAttributes( return size; } -static void -SISVideoTimerCallback(ScrnInfoPtr pScrn, Time now) -{ - SISPtr pSiS = SISPTR(pScrn); - SISPortPrivPtr pPriv = NULL; - unsigned char sridx, cridx; - - pSiS->VideoTimerCallback = NULL; - - if(!pScrn->vtSema) return; - - if(pSiS->adaptor) { - pPriv = GET_PORT_PRIVATE(pScrn); - if(!pPriv->videoStatus) - pPriv = NULL; - } - - if(pPriv) { - if(pPriv->videoStatus & TIMER_MASK) { - UpdateCurrentTime(); - if(pPriv->offTime < currentTime.milliseconds) { - if(pPriv->videoStatus & OFF_TIMER) { - /* 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 = currentTime.milliseconds + FREE_DELAY; - pSiS->VideoTimerCallback = SISVideoTimerCallback; - } else if(pPriv->videoStatus & FREE_TIMER) { - SISFreeOverlayMemory(pScrn); - pPriv->mustwait = 1; - pPriv->videoStatus = 0; - } - } else - pSiS->VideoTimerCallback = SISVideoTimerCallback; - } - } -} - -/* Offscreen surface stuff */ +/*****************************************************************/ +/* OFFSCREEN SURFACES */ +/*****************************************************************/ static int SISAllocSurface ( @@ -3725,9 +4332,9 @@ SISStopSurface (XF86SurfacePtr surface) SISPtr pSiS = SISPTR(surface->pScrn); if(pPriv->grabbedByV4L && pPriv->videoStatus) { - close_overlay(pSiS, pPriv); - pPriv->mustwait = 1; - pPriv->videoStatus = 0; + close_overlay(pSiS, pPriv); + pPriv->mustwait = 1; + pPriv->videoStatus = 0; } return Success; } @@ -3738,9 +4345,9 @@ SISFreeSurface (XF86SurfacePtr surface) SISPortPrivPtr pPriv = (SISPortPrivPtr)(surface->devPrivate.ptr); if(pPriv->grabbedByV4L) { - SISStopSurface(surface); - SISFreeOverlayMemory(surface->pScrn); - pPriv->grabbedByV4L = FALSE; + SISStopSurface(surface); + SISFreeOverlayMemory(surface->pScrn); + pPriv->grabbedByV4L = FALSE; } return Success; } @@ -3788,8 +4395,7 @@ SISDisplaySurface ( xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Xv: DisplaySurface called\n"); #endif - if(!pPriv->grabbedByV4L) - return Success; + if(!pPriv->grabbedByV4L) return Success; pPriv->drw_x = drw_x; pPriv->drw_y = drw_y; @@ -3808,8 +4414,10 @@ SISDisplaySurface ( SISDisplayVideo(pScrn, pPriv); if(pPriv->autopaintColorKey) { - if((pPriv->NoOverlay) && (!(pSiS->NoAccel))) { - XAAFillMono8x8PatternRects(pScrn, + 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), @@ -3817,8 +4425,8 @@ SISDisplaySurface ( 0x00422418, 0x18244200, 0, 0); } else { -#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,3,99,0,0) - XAAFillSolidRects(pScrn, pPriv->colorKey, GXcopy, ~0, +#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 @@ -3934,209 +4542,635 @@ SISInitOffscreenImages(ScreenPtr pScreen) xf86XVRegisterOffscreenImages(pScreen, SISOffscreenImages, num); } -#ifdef NOT_YET_IMPLEMENTED /* ----------- TW: FOR FUTURE USE -------------------- */ +/*****************************************************************/ +/* BLIT ADAPTORS */ +/*****************************************************************/ +#ifdef INCL_YUV_BLIT_ADAPTOR -/* Set alpha - does not work */ static void -set_alpha(SISPtr pSiS, CARD8 alpha) +SISSetPortDefaultsBlit(ScrnInfoPtr pScrn, SISBPortPrivPtr pPriv) { - setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, ((alpha & 0x0f) << 4), 0xf0); + /* Default: Don't sync. */ + pPriv->vsync = 0; } -/* Set SubPicture Start Address (yet unused) */ static void -set_subpict_start_offset(SISPtr pSiS, SISOverlayPtr pOverlay, int index) +SISResetVideoBlit(ScrnInfoPtr pScrn) { - CARD32 temp; - CARD8 data; - - temp = pOverlay->SubPictAddr >> 4; /* 630 <-> 315 shiftValue? */ - - setvideoreg(pSiS,Index_VI_SubPict_Buf_Start_Low, temp & 0xFF); - setvideoreg(pSiS,Index_VI_SubPict_Buf_Start_Middle, (temp>>8) & 0xFF); - setvideoreg(pSiS,Index_VI_SubPict_Buf_Start_High, (temp>>16) & 0x3F); - if(pSiS->VGAEngine == SIS_315_VGA) { - setvideoreg(pSiS,Index_VI_SubPict_Start_Over, (temp>>22) & 0x01); - /* Submit SubPict offset ? */ - /* data=getvideoreg(pSiS,Index_VI_Control_Misc3); */ - setvideoreg(pSiS,Index_VI_Control_Misc3, (1 << index) | 0x04); - } } -/* Set SubPicture Pitch (yet unused) */ -static void -set_subpict_pitch(SISPtr pSiS, SISOverlayPtr pOverlay, int index) +static XF86VideoAdaptorPtr +SISSetupBlitVideo(ScreenPtr pScreen) { - CARD32 temp; - CARD8 data; - - temp = pOverlay->SubPictPitch >> 4; /* 630 <-> 315 shiftValue? */ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + SISPtr pSiS = SISPTR(pScrn); + XF86VideoAdaptorPtr adapt; + SISBPortPrivPtr pPriv; + int i; - setvideoreg(pSiS,Index_VI_SubPict_Buf_Pitch, temp & 0xFF); - if(pSiS->VGAEngine == SIS_315_VGA) { - setvideoreg(pSiS,Index_VI_SubPict_Buf_Pitch_High, (temp>>8) & 0xFF); - /* Submit SubPict pitch ? */ - /* data=getvideoreg(pSiS,Index_VI_Control_Misc3); */ - setvideoreg(pSiS,Index_VI_Control_Misc3, (1 << index) | 0x04); - } -} + if(!pSiS->AccelInfoPtr) return NULL; -/* Calculate and set SubPicture scaling (untested, unused yet) */ -static void -set_subpict_scale_factor(SISOverlayPtr pOverlay, ScrnInfoPtr pScrn, - SISPortPrivPtr pPriv, int index, int iscrt2) -{ - SISPtr pSiS = SISPTR(pScrn); - CARD32 I=0,mult=0; - int flag=0; - - int dstW = pOverlay->SubPictdstBox.x2 - pOverlay->SubPictdstBox.x1; - int dstH = pOverlay->SubPictdstBox.y2 - pOverlay->SubPictdstBox.y1; - int srcW = pOverlay->SubPictsrcW; - int srcH = pOverlay->SubPictsrcH; - CARD16 LCDheight = pSiS->LCDheight; - int srcPitch = pOverlay->SubPictOrigPitch; - int origdstH = dstH; + if(!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) + + (sizeof(DevUnion) * NUM_BLIT_PORTS) + + sizeof(SISBPortPrivRec)))) { + return NULL; + } - /* Stretch image due to idiotic LCD "auto"-scaling */ - /* INCOMPLETE and INCORRECT - See set_scale_factor() */ - if( (pPriv->bridgeIsSlave) && (pSiS->VBFlags & CRT2_LCD) ) { - dstH = (dstH * LCDheight) / pOverlay->SCREENheight; - } else if((index) && (pSiS->VBFlags & CRT2_LCD)) { - dstH = (dstH * LCDheight) / pOverlay->SCREENheight; - if(pPriv->displayMode == DISPMODE_MIRROR) flag = 1; - } + adapt->type = XvWindowMask | XvInputMask | XvImageMask; + adapt->flags = 0; + adapt->name = "SIS 315/330 series Video Blitter"; + adapt->nEncodings = 1; + adapt->pEncodings = &DummyEncodingBlit; + adapt->nFormats = 4; + 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 = (unsigned long)(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->linear[i] = NULL; + } + + if(pSiS->sishw_ext.jChipType >= SIS_330) { + pPriv->AccelCmd = YUVRGB_BLIT_330; + pPriv->VBlankTriggerCRT1 = 0; + pPriv->VBlankTriggerCRT2 = 0; + } else { + pPriv->AccelCmd = YUVRGB_BLIT_325; + pPriv->VBlankTriggerCRT1 = SCANLINE_TRIGGER_ENABLE | SCANLINE_TR_CRT1; + pPriv->VBlankTriggerCRT2 = SCANLINE_TRIGGER_ENABLE | SCANLINE_TR_CRT2; + } + + 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; - if(dstW == srcW) { - pOverlay->SubPictHUSF = 0x00; - pOverlay->SubPictIntBit = 0x01; - } else if(dstW > srcW) { - pOverlay->SubPictHUSF = (srcW << 16) / dstW; - pOverlay->SubPictIntBit = 0x00; - } else { - int tmpW = dstW; + pSiS->xvVSync = MAKE_ATOM(sisxvvsync); + pSiS->xvSetDefaults = MAKE_ATOM(sisxvsetdefaults); + + SISResetVideoBlit(pScrn); + + /* Reset the properties to their defaults */ + SISSetPortDefaultsBlit(pScrn, pPriv); - I = 0x00; - while (srcW >= tmpW) { - tmpW <<= 1; - I++; - } - pOverlay->SubPictwHPre = (CARD8)(I - 1); - dstW <<= (I - 1); - if((srcW % dstW)) - pOverlay->SubPictHUSF = ((srcW - dstW) << 16) / dstW; - else - pOverlay->SubPictHUSF = 0x00; + return adapt; +} - pOverlay->SubPictIntBit = 0x01; - } +static void +SISFreeBlitMemory(ScrnInfoPtr pScrn, int index) +{ + SISPtr pSiS = SISPTR(pScrn); + SISBPortPrivPtr pPriv = (SISBPortPrivPtr)(pSiS->blitPriv); - if(dstH == srcH) { - pOverlay->SubPictVUSF = 0x00; - pOverlay->SubPictIntBit |= 0x02; - } else if(dstH > srcH) { - dstH += 0x02; - pOverlay->SubPictVUSF = (srcH << 16) / dstH; - /* pOverlay->SubPictIntBit |= 0x00; */ - } else { - CARD32 realI; + if(pPriv->linear[index]) { + xf86FreeOffscreenLinear(pPriv->linear[index]); + pPriv->linear[index] = NULL; + } +} - I = realI = srcH / dstH; - pOverlay->SubPictIntBit |= 0x02; +static int +SISGetPortAttributeBlit(ScrnInfoPtr pScrn, Atom attribute, + INT32 *value, unsigned long index) +{ + SISPtr pSiS = SISPTR(pScrn); + SISBPortPrivPtr pPriv = (SISBPortPrivPtr)(pSiS->blitPriv); - if(I < 2) { - pOverlay->SubPictVUSF = ((srcH - dstH) << 16) / dstH; - /* TW: Needed for LCD-scaling modes */ - if((flag) && (mult = (srcH / origdstH)) >= 2) - pOverlay->SubPictPitch /= mult; - } else { - if(((srcPitch * I)>>2) > 0xFFF) { - I = (0xFFF*2/srcPitch); - pOverlay->SubPictVUSF = 0xFFFF; - } else { - dstH = I * dstH; - if(srcH % dstH) - pOverlay->SubPictVUSF = ((srcH - dstH) << 16) / dstH; - else - pOverlay->SubPictVUSF = 0x00; - } - /* set video frame buffer offset */ - pOverlay->SubPictPitch = (CARD16)(srcPitch*I); - } - } - /* set SubPicture scale factor */ - setvideoreg (pSiS, Index_VI_SubPict_Hor_Scale_Low, (CARD8)(pOverlay->SubPictHUSF)); - setvideoreg (pSiS, Index_VI_SubPict_Hor_Scale_High, (CARD8)((pOverlay->SubPictHUSF)>>8)); - setvideoreg (pSiS, Index_VI_SubPict_Vert_Scale_Low, (CARD8)(pOverlay->SubPictVUSF)); - setvideoreg (pSiS, Index_VI_SubPict_Vert_Scale_High,(CARD8)((pOverlay->SubPictVUSF)>>8)); - - setvideoregmask (pSiS, Index_VI_SubPict_Scale_Control, - (pOverlay->SubPictIntBit << 3) | - (pOverlay->SubPictwHPre), 0x7f); + if(attribute == pSiS->xvVSync) { + *value = pPriv->vsync; + } else return BadMatch; + return Success; } -/* Set SubPicture Preset (yet unused) */ -static void -set_subpict_preset(SISPtr pSiS, SISOverlayPtr pOverlay) +static int +SISSetPortAttributeBlit(ScrnInfoPtr pScrn, Atom attribute, + INT32 value, unsigned long index) { - CARD32 temp; - CARD8 data; - - temp = pOverlay->SubPictPreset >> 4; /* TW: 630 <-> 315 ? */ - - setvideoreg(pSiS,Index_VI_SubPict_Buf_Preset_Low, temp & 0xFF); - setvideoreg(pSiS,Index_VI_SubPict_Buf_Preset_Middle, (temp>>8) & 0xFF); - data = getvideoreg(pSiS,Index_VI_SubPict_Buf_Start_High); - if(temp > 0xFFFF) - data |= 0x40; - else - data &= ~0x40; - setvideoreg(pSiS,Index_VI_SubPict_Buf_Start_High, data); + 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 -enable_subpict_overlay(SISPtr pSiS, Bool enable) +SISStopVideoBlit(ScrnInfoPtr pScrn, unsigned long index, Bool shutdown) { - setvideoregmask(pSiS, Index_VI_SubPict_Scale_Control, - enable ? 0x40 : 0x00, - 0x40); + 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) { + XAAInfoRecPtr pXAA = pSiS->AccelInfoPtr; + pPriv->videoStatus[index] = 0; + if(pXAA && pXAA->Sync) (pXAA->Sync)(pScrn); + SISFreeBlitMemory(pScrn, (int)index); + } } -/* Set overlay for subpicture */ static void -set_subpict_overlay(SISPtr pSiS, SISOverlayPtr pOverlay, SISPortPrivPtr pPriv, int index) +SISWriteBlitPacket(SISPtr pSiS, CARD32 *packet) { - ScrnInfoPtr pScrn = pSiS->pScrn; + CARD32 dummybuf; + + SiSWritePacketPart(packet[0], packet[1], packet[2], packet[3]); + SiSWritePacketPart(packet[4], packet[5], packet[6], packet[7]); + SiSWritePacketPart(packet[8], packet[9], packet[10], packet[11]); + SiSWritePacketPart(packet[12], packet[13], packet[14], packet[15]); + SiSWritePacketPart(packet[16], packet[17], packet[18], packet[19]); + SiSSyncWP; +} + +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, unsigned char* buf, + short width, short height, + Bool sync, + RegionPtr clipBoxes, unsigned long index +){ + 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); + int depth = pSiS->CurrentLayout.bitsPerPixel >> 3; + CARD32 dstbase = 0, offsety, offsetuv, temp; + int totalSize, bytesize=0, h, w, wb, srcPitch; + int xoffset = 0, yoffset = 0, left, right, top, bottom; + unsigned char *ybases, *ubases = NULL, *vbases = NULL, *myubases, *myvbases; + unsigned char *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->linear[index] = SISAllocateOverlayMemory(pScrn, pPriv->linear[index], totalSize<<1))) + return BadAlloc; + + /* fixup pointers */ + pPriv->bufAddr[index][0] = (pPriv->linear[index]->offset * depth); + 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 */ + memcpy(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: + memcpy(ybased, ybases, totalSize); + } + +#ifdef SISDUALHEAD + dstbase += HEADOFFSET; +#endif - set_subpict_pitch(pSiS, &overlay, index); - set_subpict_start_offset(pSiS, &overlay, index); - set_subpict_scale_factor(&overlay, pScrn, pPriv, index); - /* set_subpict_preset(pSiS, &overlay); */ - /* enable_subpict_overlay(pSiS, 1); */ + 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 = 0xffff; + + MyPacket.P12_Command |= pPriv->AccelCmd | + SRCVIDEO | + PATFG | + pSiS->SiS310_AccelDepth | + YUV_CMD_YUV | + DSTVIDEO; + + 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 + } + + 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; + +#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 + + 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; + MyPacket.P12_UVSrcAddr = pPriv->bufAddr[index][pPriv->currentBuf[index]] + bytesize + offsetuv; + SISWriteBlitPacket(pSiS, (CARD32*)&MyPacket); + MyPacket.P12_Command &= ~(pPriv->VBlankTriggerCRT1 | pPriv->VBlankTriggerCRT2); + first = FALSE; +mycont: + pbox++; + } + +#if 0 + { + int debug = 0; + while( (MMIO_IN16(pSiS->IOBase, Q_STATUS+2) & 0x8000) != 0x8000) { debug++; }; + while( (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, + unsigned short *w, unsigned short *h, + int *pitches, int *offsets +){ + int pitchY, pitchUV; + int size, sizeY, sizeUV; -/* Set MPEG Field Preset (yet unused) */ -static void -set_mpegfield_preset(SISPtr pSiS, SISOverlayPtr pOverlay) -{ - setvideoreg(pSiS,Index_MPEG_Y_Buf_Preset_Low, pOverlay->MPEG_Y & 0xFF); - setvideoreg(pSiS,Index_MPEG_Y_Buf_Preset_Middle, (pOverlay->MPEG_Y>>8) & 0xFF); + if(*w > DummyEncodingBlit.width) *w = DummyEncodingBlit.width; + if(*h > DummyEncodingBlit.height) *h = DummyEncodingBlit.height; - setvideoreg(pSiS,Index_MPEG_UV_Buf_Preset_Low, pOverlay->MPEG_UV & 0xFF); - setvideoreg(pSiS,Index_MPEG_UV_Buf_Preset_Middle, (pOverlay->MPEG_UV>>8) & 0xFF); + 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; + } - setvideoreg(pSiS,Index_MPEG_Y_UV_Buf_Preset_High, - ((pOverlay->MPEG_Y>>16) & 0x0F) | ((pOverlay->MPEG_UV>>12) & 0xF0)); + return size; } static void -set_mpegfield_scale(SISPtr pSiS, SISOverlayPtr pOverlay) -{ - /* Empty for now */ +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, + unsigned long index +){ + /* We cannot scale */ + *p_w = vid_w; + *p_h = vid_h; } +#endif /* INCL_YUV */ -#endif /* ------------------------------------------------------------------- */ +/*****************************************/ +/* TIMER CALLBACK */ +/*****************************************/ +static void +SISVideoTimerCallback(ScrnInfoPtr pScrn, Time now) +{ + SISPtr pSiS = SISPTR(pScrn); + SISPortPrivPtr pPriv = NULL; + SISBPortPrivPtr pPrivBlit = NULL; + unsigned char 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) { + SISFreeOverlayMemory(pScrn); + 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) { + SISFreeBlitMemory(pScrn, i); + pPrivBlit->videoStatus[i] = 0; + } else { + setcallback = TRUE; + } + } + } + } +#endif + + pSiS->VideoTimerCallback = (setcallback) ? SISVideoTimerCallback : NULL; +} |