sis6326_video.c revision 72b676d7
172b676d7Smrg/* $XFree86$ */ 272b676d7Smrg/* $XdotOrg: driver/xf86-video-sis/src/sis6326_video.c,v 1.19 2005/10/16 18:12:32 twini Exp $ */ 372b676d7Smrg/* 472b676d7Smrg * Xv driver for SiS 5597/5598, 6326 and 530/620. 572b676d7Smrg * 672b676d7Smrg * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria. 772b676d7Smrg * 872b676d7Smrg * Redistribution and use in source and binary forms, with or without 972b676d7Smrg * modification, are permitted provided that the following conditions 1072b676d7Smrg * are met: 1172b676d7Smrg * 1) Redistributions of source code must retain the above copyright 1272b676d7Smrg * notice, this list of conditions and the following disclaimer. 1372b676d7Smrg * 2) Redistributions in binary form must reproduce the above copyright 1472b676d7Smrg * notice, this list of conditions and the following disclaimer in the 1572b676d7Smrg * documentation and/or other materials provided with the distribution. 1672b676d7Smrg * 3) The name of the author may not be used to endorse or promote products 1772b676d7Smrg * derived from this software without specific prior written permission. 1872b676d7Smrg * 1972b676d7Smrg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2072b676d7Smrg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2172b676d7Smrg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2272b676d7Smrg * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2372b676d7Smrg * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2472b676d7Smrg * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2572b676d7Smrg * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2672b676d7Smrg * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2772b676d7Smrg * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2872b676d7Smrg * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2972b676d7Smrg * 3072b676d7Smrg * Author: Thomas Winischhofer <thomas@winischhofer.net> 3172b676d7Smrg * 3272b676d7Smrg */ 3372b676d7Smrg 3472b676d7Smrg#ifdef HAVE_CONFIG_H 3572b676d7Smrg#include "config.h" 3672b676d7Smrg#endif 3772b676d7Smrg 3872b676d7Smrg#include "sis.h" 3972b676d7Smrg 4072b676d7Smrg#ifdef SIS_USE_XAA 4172b676d7Smrg#include "xf86fbman.h" 4272b676d7Smrg#endif 4372b676d7Smrg#include "xf86xv.h" 4472b676d7Smrg#include "regionstr.h" 4572b676d7Smrg#include <X11/extensions/Xv.h> 4672b676d7Smrg#include "dixstruct.h" 4772b676d7Smrg#include "fourcc.h" 4872b676d7Smrg 4972b676d7Smrg#define SIS_NEED_inSISREG 5072b676d7Smrg#define SIS_NEED_outSISREG 5172b676d7Smrg#define SIS_NEED_inSISIDXREG 5272b676d7Smrg#define SIS_NEED_outSISIDXREG 5372b676d7Smrg#define SIS_NEED_setSISIDXREGmask 5472b676d7Smrg#include "sis_regs.h" 5572b676d7Smrg 5672b676d7Smrg#define OFF_DELAY 200 /* milliseconds */ 5772b676d7Smrg#define FREE_DELAY 60000 5872b676d7Smrg 5972b676d7Smrg#define OFF_TIMER 0x01 6072b676d7Smrg#define FREE_TIMER 0x02 6172b676d7Smrg#define CLIENT_VIDEO_ON 0x04 6272b676d7Smrg 6372b676d7Smrg#define TIMER_MASK (OFF_TIMER | FREE_TIMER) 6472b676d7Smrg 6572b676d7Smrg#define WATCHDOG_DELAY 500000 /* Watchdog counter for Vertical Restrace waiting */ 6672b676d7Smrg 6772b676d7Smrgstatic XF86VideoAdaptorPtr SIS6326SetupImageVideo(ScreenPtr); 6872b676d7Smrgstatic void SIS6326StopVideo(ScrnInfoPtr, pointer, Bool); 6972b676d7Smrgstatic int SIS6326SetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer); 7072b676d7Smrgstatic int SIS6326GetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer); 7172b676d7Smrgstatic void SIS6326QueryBestSize(ScrnInfoPtr, Bool, short, short, short, 7272b676d7Smrg short, unsigned int *,unsigned int *, pointer); 7372b676d7Smrgstatic int SIS6326PutImage( ScrnInfoPtr, 7472b676d7Smrg short, short, short, short, short, short, short, short, 7572b676d7Smrg int, unsigned char*, short, short, Bool, RegionPtr, pointer, 7672b676d7Smrg DrawablePtr); 7772b676d7Smrgstatic int SIS6326QueryImageAttributes(ScrnInfoPtr, 7872b676d7Smrg int, unsigned short *, unsigned short *, int *, int *); 7972b676d7Smrgstatic void SIS6326VideoTimerCallback(ScrnInfoPtr pScrn, Time now); 8072b676d7Smrgstatic void SIS6326InitOffscreenImages(ScreenPtr pScrn); 8172b676d7Smrg 8272b676d7Smrgextern unsigned int SISAllocateFBMemory(ScrnInfoPtr pScrn, void **handle, int bytesize); 8372b676d7Smrgextern void SISFreeFBMemory(ScrnInfoPtr pScrn, void **handle); 8472b676d7Smrg 8572b676d7Smrg#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) 8672b676d7Smrg 8772b676d7Smrgstatic Atom xvBrightness, xvContrast, xvColorKey; 8872b676d7Smrgstatic Atom xvAutopaintColorKey, xvSetDefaults; 8972b676d7Smrgstatic Atom xvDisableGfx; 9072b676d7Smrg 9172b676d7Smrg#define IMAGE_MIN_WIDTH 32 /* Minimum and maximum image sizes */ 9272b676d7Smrg#define IMAGE_MIN_HEIGHT 24 9372b676d7Smrg#define IMAGE_MAX_WIDTH 720 /* Are these correct for the chips ? */ 9472b676d7Smrg#define IMAGE_MAX_HEIGHT 576 9572b676d7Smrg#define IMAGE_MAX_WIDTH_5597 384 9672b676d7Smrg#define IMAGE_MAX_HEIGHT_5597 288 9772b676d7Smrg 9872b676d7Smrg#if 0 9972b676d7Smrgstatic int oldH, oldW; 10072b676d7Smrg#endif 10172b676d7Smrg 10272b676d7Smrg/**************************************************************************** 10372b676d7Smrg * Raw register access : These routines directly interact with the sis's 10472b676d7Smrg * control aperature. Must not be called until after 10572b676d7Smrg * the board's pci memory has been mapped. 10672b676d7Smrg ****************************************************************************/ 10772b676d7Smrg 10872b676d7Smrg#if 0 10972b676d7Smrgstatic CARD32 _sisread(SISPtr pSiS, CARD32 reg) 11072b676d7Smrg{ 11172b676d7Smrg return *(pSiS->IOBase + reg); 11272b676d7Smrg} 11372b676d7Smrg 11472b676d7Smrgstatic void _siswrite(SISPtr pSiS, CARD32 reg, CARD32 data) 11572b676d7Smrg{ 11672b676d7Smrg *(pSiS->IOBase + reg) = data; 11772b676d7Smrg} 11872b676d7Smrg#endif 11972b676d7Smrg 12072b676d7Smrgstatic CARD8 getvideoreg(SISPtr pSiS, CARD8 reg) 12172b676d7Smrg{ 12272b676d7Smrg CARD8 ret; 12372b676d7Smrg inSISIDXREG(SISCR, reg, ret); 12472b676d7Smrg return ret; 12572b676d7Smrg} 12672b676d7Smrg 12772b676d7Smrgstatic __inline void setvideoreg(SISPtr pSiS, CARD8 reg, CARD8 data) 12872b676d7Smrg{ 12972b676d7Smrg outSISIDXREG(SISCR, reg, data); 13072b676d7Smrg} 13172b676d7Smrg 13272b676d7Smrgstatic __inline void setvideoregmask(SISPtr pSiS, CARD8 reg, CARD8 data, CARD8 mask) 13372b676d7Smrg{ 13472b676d7Smrg setSISIDXREGmask(SISCR, reg, data, mask); 13572b676d7Smrg} 13672b676d7Smrg 13772b676d7Smrg/* VBlank */ 13872b676d7Smrgstatic CARD8 vblank_active_CRT1(SISPtr pSiS) 13972b676d7Smrg{ 14072b676d7Smrg return (inSISREG(SISINPSTAT) & 0x08); 14172b676d7Smrg} 14272b676d7Smrg 14372b676d7Smrg/* Scanline - unused */ 14472b676d7Smrg#if 0 14572b676d7Smrgstatic CARD32 get_scanline_CRT1(SISPtr pSiS) 14672b676d7Smrg{ 14772b676d7Smrg CARD8 temp; 14872b676d7Smrg 14972b676d7Smrg temp = getvideoreg(pSiS, 0x20); 15072b676d7Smrg temp = getvideoreg(pSiS, 0x1b); 15172b676d7Smrg return((getvideoreg(pSiS, 0x1d) << 8) | getvideoreg(pSiS, 0x1c)); 15272b676d7Smrg} 15372b676d7Smrg#endif 15472b676d7Smrg 15572b676d7Smrgvoid SIS6326InitVideo(ScreenPtr pScreen) 15672b676d7Smrg{ 15772b676d7Smrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 15872b676d7Smrg XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; 15972b676d7Smrg XF86VideoAdaptorPtr newAdaptor = NULL; 16072b676d7Smrg int num_adaptors; 16172b676d7Smrg 16272b676d7Smrg newAdaptor = SIS6326SetupImageVideo(pScreen); 16372b676d7Smrg if(newAdaptor) { 16472b676d7Smrg SIS6326InitOffscreenImages(pScreen); 16572b676d7Smrg } 16672b676d7Smrg 16772b676d7Smrg num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); 16872b676d7Smrg 16972b676d7Smrg if(newAdaptor) { 17072b676d7Smrg if(!num_adaptors) { 17172b676d7Smrg num_adaptors = 1; 17272b676d7Smrg adaptors = &newAdaptor; 17372b676d7Smrg } else { 17472b676d7Smrg /* need to free this someplace */ 17572b676d7Smrg newAdaptors = xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*)); 17672b676d7Smrg if(newAdaptors) { 17772b676d7Smrg memcpy(newAdaptors, adaptors, num_adaptors * 17872b676d7Smrg sizeof(XF86VideoAdaptorPtr)); 17972b676d7Smrg newAdaptors[num_adaptors] = newAdaptor; 18072b676d7Smrg adaptors = newAdaptors; 18172b676d7Smrg num_adaptors++; 18272b676d7Smrg } 18372b676d7Smrg } 18472b676d7Smrg } 18572b676d7Smrg 18672b676d7Smrg if(num_adaptors) 18772b676d7Smrg xf86XVScreenInit(pScreen, adaptors, num_adaptors); 18872b676d7Smrg 18972b676d7Smrg if(newAdaptors) 19072b676d7Smrg xfree(newAdaptors); 19172b676d7Smrg} 19272b676d7Smrg 19372b676d7Smrg/* client libraries expect an encoding */ 19472b676d7Smrgstatic XF86VideoEncodingRec DummyEncoding = 19572b676d7Smrg{ 19672b676d7Smrg 0, 19772b676d7Smrg "XV_IMAGE", 19872b676d7Smrg IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT, 19972b676d7Smrg {1, 1} 20072b676d7Smrg}; 20172b676d7Smrg 20272b676d7Smrgstatic XF86VideoEncodingRec DummyEncoding5597 = 20372b676d7Smrg{ 20472b676d7Smrg 0, 20572b676d7Smrg "XV_IMAGE", 20672b676d7Smrg IMAGE_MAX_WIDTH_5597, IMAGE_MAX_HEIGHT_5597, 20772b676d7Smrg {1, 1} 20872b676d7Smrg}; 20972b676d7Smrg 21072b676d7Smrg#define NUM_FORMATS 4 21172b676d7Smrg 21272b676d7Smrgstatic XF86VideoFormatRec SIS6326Formats[NUM_FORMATS] = 21372b676d7Smrg{ 21472b676d7Smrg { 8, PseudoColor}, 21572b676d7Smrg {15, TrueColor}, 21672b676d7Smrg {16, TrueColor}, 21772b676d7Smrg {24, TrueColor} 21872b676d7Smrg}; 21972b676d7Smrg 22072b676d7Smrg#define NUM_ATTRIBUTES 6 22172b676d7Smrg 22272b676d7Smrgstatic XF86AttributeRec SIS6326Attributes[NUM_ATTRIBUTES] = 22372b676d7Smrg{ 22472b676d7Smrg {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, 22572b676d7Smrg {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"}, 22672b676d7Smrg {XvSettable | XvGettable, 0, 7, "XV_CONTRAST"}, 22772b676d7Smrg {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"}, 22872b676d7Smrg {XvSettable , 0, 0, "XV_SET_DEFAULTS"}, 22972b676d7Smrg {XvSettable | XvGettable, 0, 1, "XV_DISABLE_GRAPHICS"} 23072b676d7Smrg}; 23172b676d7Smrg 23272b676d7Smrg#define NUM_IMAGES 6 23372b676d7Smrg#define NUM_IMAGES_NOYV12 4 23472b676d7Smrg#define PIXEL_FMT_YV12 FOURCC_YV12 /* 0x32315659 */ 23572b676d7Smrg#define PIXEL_FMT_UYVY FOURCC_UYVY /* 0x59565955 */ 23672b676d7Smrg#define PIXEL_FMT_YUY2 FOURCC_YUY2 /* 0x32595559 */ 23772b676d7Smrg#define PIXEL_FMT_I420 FOURCC_I420 /* 0x30323449 */ 23872b676d7Smrg#define PIXEL_FMT_RGB5 0x35315652 23972b676d7Smrg#define PIXEL_FMT_RGB6 0x36315652 24072b676d7Smrg 24172b676d7Smrgstatic XF86ImageRec SIS6326Images[NUM_IMAGES] = 24272b676d7Smrg{ 24372b676d7Smrg XVIMAGE_YUY2, /* If order is changed, SIS6326OffscreenImages must be adapted */ 24472b676d7Smrg XVIMAGE_UYVY, 24572b676d7Smrg XVIMAGE_YV12, 24672b676d7Smrg XVIMAGE_I420, 24772b676d7Smrg { 24872b676d7Smrg 0x35315652, 24972b676d7Smrg XvRGB, 25072b676d7Smrg LSBFirst, 25172b676d7Smrg {'R','V','1','5', 25272b676d7Smrg 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 25372b676d7Smrg 16, 25472b676d7Smrg XvPacked, 25572b676d7Smrg 1, 25672b676d7Smrg 15, 0x7C00, 0x03E0, 0x001F, 25772b676d7Smrg 0, 0, 0, 25872b676d7Smrg 0, 0, 0, 25972b676d7Smrg 0, 0, 0, 26072b676d7Smrg {'R', 'V', 'B',0, 26172b676d7Smrg 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}, 26272b676d7Smrg XvTopToBottom 26372b676d7Smrg }, 26472b676d7Smrg { 26572b676d7Smrg 0x36315652, 26672b676d7Smrg XvRGB, 26772b676d7Smrg LSBFirst, 26872b676d7Smrg {'R','V','1','6', 26972b676d7Smrg 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 27072b676d7Smrg 16, 27172b676d7Smrg XvPacked, 27272b676d7Smrg 1, 27372b676d7Smrg 16, 0xF800, 0x07E0, 0x001F, 27472b676d7Smrg 0, 0, 0, 27572b676d7Smrg 0, 0, 0, 27672b676d7Smrg 0, 0, 0, 27772b676d7Smrg {'R', 'V', 'B',0, 27872b676d7Smrg 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}, 27972b676d7Smrg XvTopToBottom 28072b676d7Smrg } 28172b676d7Smrg}; 28272b676d7Smrg 28372b676d7Smrgstatic XF86ImageRec SIS6326ImagesNoYV12[NUM_IMAGES_NOYV12] = 28472b676d7Smrg{ 28572b676d7Smrg XVIMAGE_YUY2, /* If order is changed, SIS6326OffscreenImages must be adapted */ 28672b676d7Smrg XVIMAGE_UYVY, 28772b676d7Smrg { 28872b676d7Smrg 0x35315652, 28972b676d7Smrg XvRGB, 29072b676d7Smrg LSBFirst, 29172b676d7Smrg {'R','V','1','5', 29272b676d7Smrg 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 29372b676d7Smrg 16, 29472b676d7Smrg XvPacked, 29572b676d7Smrg 1, 29672b676d7Smrg 15, 0x7C00, 0x03E0, 0x001F, 29772b676d7Smrg 0, 0, 0, 29872b676d7Smrg 0, 0, 0, 29972b676d7Smrg 0, 0, 0, 30072b676d7Smrg {'R', 'V', 'B',0, 30172b676d7Smrg 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}, 30272b676d7Smrg XvTopToBottom 30372b676d7Smrg }, 30472b676d7Smrg { 30572b676d7Smrg 0x36315652, 30672b676d7Smrg XvRGB, 30772b676d7Smrg LSBFirst, 30872b676d7Smrg {'R','V','1','6', 30972b676d7Smrg 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 31072b676d7Smrg 16, 31172b676d7Smrg XvPacked, 31272b676d7Smrg 1, 31372b676d7Smrg 16, 0xF800, 0x07E0, 0x001F, 31472b676d7Smrg 0, 0, 0, 31572b676d7Smrg 0, 0, 0, 31672b676d7Smrg 0, 0, 0, 31772b676d7Smrg {'R', 'V', 'B',0, 31872b676d7Smrg 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}, 31972b676d7Smrg XvTopToBottom 32072b676d7Smrg } 32172b676d7Smrg}; 32272b676d7Smrg 32372b676d7Smrgtypedef struct { 32472b676d7Smrg int pixelFormat; 32572b676d7Smrg 32672b676d7Smrg CARD16 pitch; 32772b676d7Smrg 32872b676d7Smrg CARD8 keyOP; 32972b676d7Smrg 33072b676d7Smrg CARD8 HUSF; 33172b676d7Smrg CARD8 VUSF; 33272b676d7Smrg CARD8 HIntBit; 33372b676d7Smrg CARD8 wHPre; 33472b676d7Smrg CARD8 PitchMult; 33572b676d7Smrg 33672b676d7Smrg CARD16 srcW; 33772b676d7Smrg CARD16 srcH; 33872b676d7Smrg 33972b676d7Smrg BoxRec dstBox; 34072b676d7Smrg 34172b676d7Smrg CARD32 PSY; 34272b676d7Smrg CARD32 PSV; 34372b676d7Smrg CARD32 PSU; 34472b676d7Smrg CARD8 YUVEnd; 34572b676d7Smrg 34672b676d7Smrg CARD8 lineBufSize; 34772b676d7Smrg 34872b676d7Smrg CARD8 (*VBlankActiveFunc)(SISPtr); 34972b676d7Smrg/* CARD32 (*GetScanLineFunc)(SISPtr pSiS); */ 35072b676d7Smrg 35172b676d7Smrg} SISOverlayRec, *SISOverlayPtr; 35272b676d7Smrg 35372b676d7Smrgtypedef struct { 35472b676d7Smrg void * handle; 35572b676d7Smrg CARD32 bufAddr[2]; 35672b676d7Smrg 35772b676d7Smrg unsigned char currentBuf; 35872b676d7Smrg 35972b676d7Smrg short drw_x, drw_y, drw_w, drw_h; 36072b676d7Smrg short src_x, src_y, src_w, src_h; 36172b676d7Smrg int id; 36272b676d7Smrg short srcPitch, height, width; 36372b676d7Smrg CARD32 totalSize; 36472b676d7Smrg 36572b676d7Smrg char brightness; 36672b676d7Smrg unsigned char contrast; 36772b676d7Smrg 36872b676d7Smrg RegionRec clip; 36972b676d7Smrg CARD32 colorKey; 37072b676d7Smrg Bool autopaintColorKey; 37172b676d7Smrg 37272b676d7Smrg Bool disablegfx; 37372b676d7Smrg 37472b676d7Smrg CARD32 videoStatus; 37572b676d7Smrg Time offTime; 37672b676d7Smrg Time freeTime; 37772b676d7Smrg 37872b676d7Smrg short oldx1, oldx2, oldy1, oldy2; 37972b676d7Smrg int mustwait; 38072b676d7Smrg 38172b676d7Smrg Bool grabbedByV4L; /* V4L stuff */ 38272b676d7Smrg int pitch; 38372b676d7Smrg int offset; 38472b676d7Smrg 38572b676d7Smrg} SISPortPrivRec, *SISPortPrivPtr; 38672b676d7Smrg 38772b676d7Smrg#define GET_PORT_PRIVATE(pScrn) \ 38872b676d7Smrg (SISPortPrivPtr)((SISPTR(pScrn))->adaptor->pPortPrivates[0].ptr) 38972b676d7Smrg 39072b676d7Smrgstatic void 39172b676d7SmrgSIS6326SetPortDefaults(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) 39272b676d7Smrg{ 39372b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 39472b676d7Smrg 39572b676d7Smrg pPriv->colorKey = 0x000101fe; 39672b676d7Smrg pPriv->videoStatus = 0; 39772b676d7Smrg pPriv->brightness = pSiS->XvDefBri; /* 0; - see sis_opt.c */ 39872b676d7Smrg pPriv->contrast = pSiS->XvDefCon; /* 4; */ 39972b676d7Smrg pPriv->autopaintColorKey = TRUE; 40072b676d7Smrg pPriv->disablegfx = pSiS->XvDefDisableGfx; 40172b676d7Smrg} 40272b676d7Smrg 40372b676d7Smrgstatic void 40472b676d7SmrgSIS6326ResetVideo(ScrnInfoPtr pScrn) 40572b676d7Smrg{ 40672b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 40772b676d7Smrg 40872b676d7Smrg /* Unlock registers */ 40972b676d7Smrg#ifdef UNLOCK_ALWAYS 41072b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 41172b676d7Smrg#endif 41272b676d7Smrg if(getvideoreg(pSiS, Index_VI6326_Passwd) != 0xa1) { 41372b676d7Smrg setvideoreg(pSiS, Index_VI6326_Passwd, 0x86); 41472b676d7Smrg if(getvideoreg(pSiS, Index_VI6326_Passwd) != 0xa1) 41572b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 41672b676d7Smrg "Xv: Video password could not unlock video registers\n"); 41772b676d7Smrg } 41872b676d7Smrg 41972b676d7Smrg /* Initialize the overlay ----------------------------------- */ 42072b676d7Smrg 42172b676d7Smrg switch(pSiS->Chipset) { 42272b676d7Smrg case PCI_CHIP_SIS5597: 42372b676d7Smrg /* Disable overlay (D[1]) & capture (D[0]) */ 42472b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Control_Misc0, 0x00, 0x03); 42572b676d7Smrg 42672b676d7Smrg /* What do these do? (Datasheet names these bits "reserved") */ 42772b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Control_Misc0, 0x00, 0x18); 42872b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Control_Misc0, 0x00, 0x0c); 42972b676d7Smrg 43072b676d7Smrg /* Select YUV format (D[6]) and "gfx + video" mode (D[4]), odd polarity? (D[7]) */ 43172b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Control_Misc0, 0x40, 0xD0); 43272b676d7Smrg /* No interrupt, no filter, disable dithering */ 43372b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Control_Misc1, 0x00, 0x7A); 43472b676d7Smrg /* Disable Brooktree support (D[6]) and system memory framebuffer (D[7]) */ 43572b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Control_Misc3, 0x00, 0xC0); 43672b676d7Smrg /* Disable video decimation (has a really strange effect if enabled) */ 43772b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Control_Misc6, 0x00, 0x80); 43872b676d7Smrg break; 43972b676d7Smrg case PCI_CHIP_SIS6326: 44072b676d7Smrg /* Disable overlay (D[1]) & capture (D[0]) */ 44172b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Control_Misc0, 0x00, 0x03); 44272b676d7Smrg 44372b676d7Smrg /* What do these do? (Datasheet names these bits "reserved") */ 44472b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Control_Misc0, 0x00, 0x18); 44572b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Control_Misc0, 0x00, 0x0c); 44672b676d7Smrg 44772b676d7Smrg /* Select YUV format (D[6]) and "gfx + video" mode (D[4]), odd polarity? (D[7]) */ 44872b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Control_Misc0, 0x40, 0xD0); 44972b676d7Smrg /* No interrupt, no filter, disable dithering */ 45072b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Control_Misc1, 0x00, 0x7A); 45172b676d7Smrg /* Disable VMI (D[4:3]), Brooktree support (D[6]) and system memory framebuffer (D[7]) */ 45272b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Control_Misc3, 0x00, 0xF8); 45372b676d7Smrg /* Disable video decimation */ 45472b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Control_Misc6, 0x00, 0x80); 45572b676d7Smrg break; 45672b676d7Smrg case PCI_CHIP_SIS530: 45772b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Control_Misc4, 0x40, 0x40); 45872b676d7Smrg /* Disable overlay (D[1]) */ 45972b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Control_Misc0, 0x00, 0x02); 46072b676d7Smrg 46172b676d7Smrg /* What do D[3:2] do? (Datasheet names these bits "reserved") */ 46272b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Control_Misc0, 0x00, 0x18); 46372b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Control_Misc0, 0x00, 0x0c); 46472b676d7Smrg 46572b676d7Smrg /* Select YUV format (D[6]) and "gfx + video" mode (D[4]) */ 46672b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Control_Misc0, 0x40, 0x50); 46772b676d7Smrg break; 46872b676d7Smrg default: 46972b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 47072b676d7Smrg "Internal error: SiS6326ResetVideo() called with invalid chipset (%x)\n", 47172b676d7Smrg pSiS->Chipset); 47272b676d7Smrg return; 47372b676d7Smrg } 47472b676d7Smrg 47572b676d7Smrg /* Clear format selection */ 47672b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Control_Misc1, 0x00, 0x04); 47772b676d7Smrg if(pSiS->oldChipset >= OC_SIS5597) { 47872b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Control_Misc4, 0x00, 0x05); 47972b676d7Smrg } 48072b676d7Smrg 48172b676d7Smrg /* Select RGB Chromakey format (D[2]=0), CCIR 601 UV data format (D[1]=0) */ 48272b676d7Smrg /* D[1]: 1 = 2's complement, 0 = CCIR 601 format */ 48372b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Control_Misc3, 0x00, 0x06); 48472b676d7Smrg 48572b676d7Smrg /* Reset contrast control */ 48672b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Contrast_Enh_Ctrl, 0x04, 0x1F); 48772b676d7Smrg 48872b676d7Smrg /* Set threshold */ 48972b676d7Smrg if(pSiS->oldChipset < OC_SIS6326) { 49072b676d7Smrg CARD8 temp; 49172b676d7Smrg inSISIDXREG(SISSR, 0x33, temp); /* Synchronous DRAM Timing? */ 49272b676d7Smrg if(temp & 0x01) temp = 0x50; 49372b676d7Smrg else temp = 0; 49472b676d7Smrg setvideoreg(pSiS, Index_VI6326_Play_Threshold_Low, temp); 49572b676d7Smrg setvideoreg(pSiS, Index_VI6326_Play_Threshold_High, temp); 49672b676d7Smrg } else { 49772b676d7Smrg CARD8 temp; 49872b676d7Smrg setvideoreg(pSiS, Index_VI6326_Play_Threshold_Low, 0x00); 49972b676d7Smrg setvideoreg(pSiS, Index_VI6326_Play_Threshold_High, 0x00); 50072b676d7Smrg inSISIDXREG(SISSR, 0x33, temp); /* Are we using SGRAM Timing? */ 50172b676d7Smrg if(temp & 0x01) temp = 0x10; 50272b676d7Smrg else temp = 0; 50372b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Control_Misc4, temp, 0x10); 50472b676d7Smrg } 50572b676d7Smrg 50672b676d7Smrg /* set default properties for overlay ------------------------------- */ 50772b676d7Smrg 50872b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Contrast_Enh_Ctrl, 0x04, 0x07); 50972b676d7Smrg setvideoreg(pSiS, Index_VI6326_Brightness, 0x20); 51072b676d7Smrg 51172b676d7Smrg if(pSiS->oldChipset < OC_SIS6205A || pSiS->oldChipset > OC_SIS82204) { 51272b676d7Smrg setvideoregmask(pSiS, Index_VI6326_AlphaGraph, 0x00, 0xF8); 51372b676d7Smrg setvideoregmask(pSiS, Index_VI6326_AlphaVideo, 0xF8, 0xF8); 51472b676d7Smrg } else { 51572b676d7Smrg setvideoregmask(pSiS, Index_VI6326_AlphaGraph, 0x00, 0xE1); 51672b676d7Smrg setvideoregmask(pSiS, Index_VI6326_AlphaVideo, 0xE1, 0xE1); 51772b676d7Smrg } 51872b676d7Smrg 51972b676d7Smrg} 52072b676d7Smrg 52172b676d7Smrgstatic XF86VideoAdaptorPtr 52272b676d7SmrgSIS6326SetupImageVideo(ScreenPtr pScreen) 52372b676d7Smrg{ 52472b676d7Smrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 52572b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 52672b676d7Smrg XF86VideoAdaptorPtr adapt; 52772b676d7Smrg SISPortPrivPtr pPriv; 52872b676d7Smrg 52972b676d7Smrg#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,1,99,1,0) 53072b676d7Smrg XAAInfoRecPtr pXAA = pSiS->AccelInfoPtr; 53172b676d7Smrg 53272b676d7Smrg if(!pXAA || !pXAA->FillSolidRects) 53372b676d7Smrg return NULL; 53472b676d7Smrg#endif 53572b676d7Smrg 53672b676d7Smrg if(!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) + 53772b676d7Smrg sizeof(SISPortPrivRec) + 53872b676d7Smrg sizeof(DevUnion)))) 53972b676d7Smrg return NULL; 54072b676d7Smrg 54172b676d7Smrg adapt->type = XvWindowMask | XvInputMask | XvImageMask; 54272b676d7Smrg adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; 54372b676d7Smrg adapt->name = "SIS 5597/5598/6326/530/620 Video Overlay"; 54472b676d7Smrg adapt->nEncodings = 1; 54572b676d7Smrg if(pSiS->oldChipset < OC_SIS6326) { 54672b676d7Smrg adapt->pEncodings = &DummyEncoding5597; 54772b676d7Smrg } else { 54872b676d7Smrg adapt->pEncodings = &DummyEncoding; 54972b676d7Smrg } 55072b676d7Smrg adapt->nFormats = NUM_FORMATS; 55172b676d7Smrg adapt->pFormats = SIS6326Formats; 55272b676d7Smrg adapt->nPorts = 1; 55372b676d7Smrg adapt->pPortPrivates = (DevUnion*)(&adapt[1]); 55472b676d7Smrg 55572b676d7Smrg pPriv = (SISPortPrivPtr)(&adapt->pPortPrivates[1]); 55672b676d7Smrg 55772b676d7Smrg adapt->pPortPrivates[0].ptr = (pointer)(pPriv); 55872b676d7Smrg adapt->pAttributes = SIS6326Attributes; 55972b676d7Smrg adapt->nAttributes = NUM_ATTRIBUTES; 56072b676d7Smrg if(pSiS->NoYV12 == 1) { 56172b676d7Smrg adapt->nImages = NUM_IMAGES_NOYV12; 56272b676d7Smrg adapt->pImages = SIS6326ImagesNoYV12; 56372b676d7Smrg } else { 56472b676d7Smrg adapt->nImages = NUM_IMAGES; 56572b676d7Smrg adapt->pImages = SIS6326Images; 56672b676d7Smrg } 56772b676d7Smrg adapt->PutVideo = NULL; 56872b676d7Smrg adapt->PutStill = NULL; 56972b676d7Smrg adapt->GetVideo = NULL; 57072b676d7Smrg adapt->GetStill = NULL; 57172b676d7Smrg adapt->StopVideo = SIS6326StopVideo; 57272b676d7Smrg adapt->SetPortAttribute = SIS6326SetPortAttribute; 57372b676d7Smrg adapt->GetPortAttribute = SIS6326GetPortAttribute; 57472b676d7Smrg adapt->QueryBestSize = SIS6326QueryBestSize; 57572b676d7Smrg adapt->PutImage = SIS6326PutImage; 57672b676d7Smrg adapt->QueryImageAttributes = SIS6326QueryImageAttributes; 57772b676d7Smrg 57872b676d7Smrg pPriv->videoStatus = 0; 57972b676d7Smrg pPriv->currentBuf = 0; 58072b676d7Smrg pPriv->handle = NULL; 58172b676d7Smrg pPriv->grabbedByV4L= FALSE; 58272b676d7Smrg 58372b676d7Smrg SIS6326SetPortDefaults(pScrn, pPriv); 58472b676d7Smrg 58572b676d7Smrg /* gotta uninit this someplace */ 58672b676d7Smrg#if defined(REGION_NULL) 58772b676d7Smrg REGION_NULL(pScreen, &pPriv->clip); 58872b676d7Smrg#else 58972b676d7Smrg REGION_INIT(pScreen, &pPriv->clip, NullBox, 0); 59072b676d7Smrg#endif 59172b676d7Smrg 59272b676d7Smrg pSiS->adaptor = adapt; 59372b676d7Smrg 59472b676d7Smrg xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); 59572b676d7Smrg xvContrast = MAKE_ATOM("XV_CONTRAST"); 59672b676d7Smrg xvColorKey = MAKE_ATOM("XV_COLORKEY"); 59772b676d7Smrg xvAutopaintColorKey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY"); 59872b676d7Smrg xvSetDefaults = MAKE_ATOM("XV_SET_DEFAULTS"); 59972b676d7Smrg xvDisableGfx = MAKE_ATOM("XV_DISABLE_GRAPHICS"); 60072b676d7Smrg 60172b676d7Smrg SIS6326ResetVideo(pScrn); 60272b676d7Smrg pSiS->ResetXv = SIS6326ResetVideo; 60372b676d7Smrg 60472b676d7Smrg return adapt; 60572b676d7Smrg} 60672b676d7Smrg 60772b676d7Smrg#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,3,99,3,0) 60872b676d7Smrgstatic Bool 60972b676d7SmrgRegionsEqual(RegionPtr A, RegionPtr B) 61072b676d7Smrg{ 61172b676d7Smrg int *dataA, *dataB; 61272b676d7Smrg int num; 61372b676d7Smrg 61472b676d7Smrg num = REGION_NUM_RECTS(A); 61572b676d7Smrg if(num != REGION_NUM_RECTS(B)) 61672b676d7Smrg return FALSE; 61772b676d7Smrg 61872b676d7Smrg if((A->extents.x1 != B->extents.x1) || 61972b676d7Smrg (A->extents.x2 != B->extents.x2) || 62072b676d7Smrg (A->extents.y1 != B->extents.y1) || 62172b676d7Smrg (A->extents.y2 != B->extents.y2)) 62272b676d7Smrg return FALSE; 62372b676d7Smrg 62472b676d7Smrg dataA = (int*)REGION_RECTS(A); 62572b676d7Smrg dataB = (int*)REGION_RECTS(B); 62672b676d7Smrg 62772b676d7Smrg while(num--) { 62872b676d7Smrg if((dataA[0] != dataB[0]) || (dataA[1] != dataB[1])) 62972b676d7Smrg return FALSE; 63072b676d7Smrg dataA += 2; 63172b676d7Smrg dataB += 2; 63272b676d7Smrg } 63372b676d7Smrg 63472b676d7Smrg return TRUE; 63572b676d7Smrg} 63672b676d7Smrg#endif 63772b676d7Smrg 63872b676d7Smrgstatic int 63972b676d7SmrgSIS6326SetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, 64072b676d7Smrg INT32 value, pointer data) 64172b676d7Smrg{ 64272b676d7Smrg SISPortPrivPtr pPriv = (SISPortPrivPtr)data; 64372b676d7Smrg 64472b676d7Smrg if(attribute == xvBrightness) { 64572b676d7Smrg if((value < -128) || (value > 127)) 64672b676d7Smrg return BadValue; 64772b676d7Smrg pPriv->brightness = value; 64872b676d7Smrg } else if(attribute == xvContrast) { 64972b676d7Smrg if((value < 0) || (value > 7)) 65072b676d7Smrg return BadValue; 65172b676d7Smrg pPriv->contrast = value; 65272b676d7Smrg } else if(attribute == xvColorKey) { 65372b676d7Smrg pPriv->colorKey = value; 65472b676d7Smrg REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 65572b676d7Smrg } else if (attribute == xvAutopaintColorKey) { 65672b676d7Smrg if((value < 0) || (value > 1)) 65772b676d7Smrg return BadValue; 65872b676d7Smrg pPriv->autopaintColorKey = value; 65972b676d7Smrg } else if(attribute == xvDisableGfx) { 66072b676d7Smrg if((value < 0) || (value > 1)) 66172b676d7Smrg return BadValue; 66272b676d7Smrg pPriv->disablegfx = value; 66372b676d7Smrg } else if (attribute == xvSetDefaults) { 66472b676d7Smrg SIS6326SetPortDefaults(pScrn, pPriv); 66572b676d7Smrg } else return BadMatch; 66672b676d7Smrg return Success; 66772b676d7Smrg} 66872b676d7Smrg 66972b676d7Smrgstatic int 67072b676d7SmrgSIS6326GetPortAttribute( 67172b676d7Smrg ScrnInfoPtr pScrn, 67272b676d7Smrg Atom attribute, 67372b676d7Smrg INT32 *value, 67472b676d7Smrg pointer data 67572b676d7Smrg){ 67672b676d7Smrg SISPortPrivPtr pPriv = (SISPortPrivPtr)data; 67772b676d7Smrg 67872b676d7Smrg if(attribute == xvBrightness) { 67972b676d7Smrg *value = pPriv->brightness; 68072b676d7Smrg } else if(attribute == xvContrast) { 68172b676d7Smrg *value = pPriv->contrast; 68272b676d7Smrg } else if(attribute == xvColorKey) { 68372b676d7Smrg *value = pPriv->colorKey; 68472b676d7Smrg } else if (attribute == xvAutopaintColorKey) { 68572b676d7Smrg *value = (pPriv->autopaintColorKey) ? 1 : 0; 68672b676d7Smrg } else if (attribute == xvDisableGfx) { 68772b676d7Smrg *value = (pPriv->disablegfx) ? 1 : 0; 68872b676d7Smrg } else return BadMatch; 68972b676d7Smrg return Success; 69072b676d7Smrg} 69172b676d7Smrg 69272b676d7Smrgstatic void 69372b676d7SmrgSIS6326QueryBestSize( 69472b676d7Smrg ScrnInfoPtr pScrn, 69572b676d7Smrg Bool motion, 69672b676d7Smrg short vid_w, short vid_h, 69772b676d7Smrg short drw_w, short drw_h, 69872b676d7Smrg unsigned int *p_w, unsigned int *p_h, 69972b676d7Smrg pointer data 70072b676d7Smrg){ 70172b676d7Smrg *p_w = drw_w; 70272b676d7Smrg *p_h = drw_h; 70372b676d7Smrg 70472b676d7Smrg /* TODO: report the HW limitation */ 70572b676d7Smrg} 70672b676d7Smrg 70772b676d7Smrgstatic void /* V 530/6326 */ 70872b676d7Smrgcalc_scale_factor(SISPtr pSiS, SISOverlayPtr pOverlay, ScrnInfoPtr pScrn, 70972b676d7Smrg SISPortPrivPtr pPriv) 71072b676d7Smrg{ 71172b676d7Smrg CARD32 temp=0; 71272b676d7Smrg 71372b676d7Smrg int dstW = pOverlay->dstBox.x2 - pOverlay->dstBox.x1; 71472b676d7Smrg int dstH = pOverlay->dstBox.y2 - pOverlay->dstBox.y1; 71572b676d7Smrg int srcW = pOverlay->srcW; 71672b676d7Smrg int srcH = pOverlay->srcH; 71772b676d7Smrg 71872b676d7Smrg /* For double scan modes, we need to double the height */ 71972b676d7Smrg if(pSiS->CurrentLayout.mode->Flags & V_DBLSCAN) { 72072b676d7Smrg dstH <<= 1; 72172b676d7Smrg } 72272b676d7Smrg /* For interlace modes, we need to half the height */ 72372b676d7Smrg if(pSiS->CurrentLayout.mode->Flags & V_INTERLACE) { 72472b676d7Smrg dstH >>= 1; 72572b676d7Smrg } 72672b676d7Smrg 72772b676d7Smrg /* Horizontal */ 72872b676d7Smrg if(dstW < IMAGE_MIN_WIDTH) dstW = IMAGE_MIN_WIDTH; 72972b676d7Smrg if(dstW == srcW) { 73072b676d7Smrg pOverlay->HUSF = 0x00; 73172b676d7Smrg pOverlay->HIntBit = 0x01; 73272b676d7Smrg } else if(dstW > srcW) { 73372b676d7Smrg pOverlay->HIntBit = 0x00; 73472b676d7Smrg temp = srcW * 64 / (dstW + 1); 73572b676d7Smrg if(temp > 63) temp = 63; 73672b676d7Smrg pOverlay->HUSF = temp; 73772b676d7Smrg } else { 73872b676d7Smrg /* 6326 can't scale below factor .440 - to check with 530/620 */ 73972b676d7Smrg if(((dstW * 1000) / srcW) < 440) dstW = ((srcW * 440) / 1000) + 1; 74072b676d7Smrg temp = srcW / dstW; 74172b676d7Smrg if(temp > 15) temp = 15; 74272b676d7Smrg pOverlay->HIntBit = temp; 74372b676d7Smrg temp = srcW * 64 / dstW; 74472b676d7Smrg pOverlay->HUSF = temp - (pOverlay->HIntBit * 64); 74572b676d7Smrg } 74672b676d7Smrg 74772b676d7Smrg /* Vertical */ 74872b676d7Smrg if(dstH < IMAGE_MIN_HEIGHT) dstH = IMAGE_MIN_HEIGHT; 74972b676d7Smrg if(dstH == srcH) { 75072b676d7Smrg pOverlay->VUSF = 0x00; 75172b676d7Smrg pOverlay->PitchMult = 1; 75272b676d7Smrg } else if(dstH > srcH) { 75372b676d7Smrg temp = srcH * 64 / (dstH + 1); 75472b676d7Smrg if (temp > 63) temp = 63; 75572b676d7Smrg pOverlay->VUSF = temp; 75672b676d7Smrg pOverlay->PitchMult = 1; 75772b676d7Smrg } else { 75872b676d7Smrg /* 6326 can't scale below factor .440 - to check with 530/620 */ 75972b676d7Smrg if(((dstH * 1000) / srcH) < 440) dstH = ((srcH * 440) / 1000) + 1; 76072b676d7Smrg temp = srcH / dstH; 76172b676d7Smrg if(srcH % dstH) { 76272b676d7Smrg temp++; 76372b676d7Smrg pOverlay->VUSF = (srcH * 64) / (temp * dstH); 76472b676d7Smrg } else { 76572b676d7Smrg pOverlay->VUSF = 0x00; 76672b676d7Smrg } 76772b676d7Smrg pOverlay->PitchMult = temp; 76872b676d7Smrg } 76972b676d7Smrg} 77072b676d7Smrg 77172b676d7Smrgstatic void 77272b676d7Smrgcalc_line_buf_size(SISOverlayPtr pOverlay) 77372b676d7Smrg{ 77472b676d7Smrg CARD32 I; 77572b676d7Smrg CARD32 line = pOverlay->srcW; 77672b676d7Smrg 77772b676d7Smrg if( (pOverlay->pixelFormat == PIXEL_FMT_YV12) || 77872b676d7Smrg (pOverlay->pixelFormat == PIXEL_FMT_I420) ) { 77972b676d7Smrg I = (line >> 5) + (((line >> 6) * 2)) + 3; 78072b676d7Smrg I <<= 5; 78172b676d7Smrg } else { /* YUV2, UYVY, RGB */ 78272b676d7Smrg I = line << 1; 78372b676d7Smrg if(I & 7) I += 8; 78472b676d7Smrg } 78572b676d7Smrg I += 8; 78672b676d7Smrg I >>= 3; 78772b676d7Smrg pOverlay->lineBufSize = (CARD8)I; 78872b676d7Smrg} 78972b676d7Smrg 79072b676d7Smrgstatic void 79172b676d7Smrgmerge_line_buf(SISPtr pSiS, SISPortPrivPtr pPriv, Bool enable) 79272b676d7Smrg{ 79372b676d7Smrg if(enable) { 79472b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Control_Misc5, 0x10, 0x10); 79572b676d7Smrg } else { 79672b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Control_Misc5, 0x00, 0x10); 79772b676d7Smrg } 79872b676d7Smrg} 79972b676d7Smrg 80072b676d7Smrgstatic void 80172b676d7Smrgset_format(SISPtr pSiS, SISOverlayPtr pOverlay) 80272b676d7Smrg{ 80372b676d7Smrg CARD8 fmt, misc0, misc1, misc4; 80472b676d7Smrg 80572b676d7Smrg switch(pOverlay->pixelFormat) { 80672b676d7Smrg case PIXEL_FMT_YV12: 80772b676d7Smrg case PIXEL_FMT_I420: /* V/530 V/6326 */ 80872b676d7Smrg fmt = 0x80; /* D[7:6] 10 YUV2(=YUYV), 01 VYUY, 00 UYVY, 11 YVYU / 00 RGB 555, 01 RGB 565 */ 80972b676d7Smrg misc0 = 0x40; /* D[6]: 1 = YUV, 0 = RGB */ 81072b676d7Smrg misc4 = 0x05; /* D[1:0] 00 RGB 555, 01 YUV 422, 10 RGB 565; D[2] 1 = YUV420 mode */ 81172b676d7Smrg misc1 = 0xff; 81272b676d7Smrg break; 81372b676d7Smrg case PIXEL_FMT_UYVY: 81472b676d7Smrg fmt = 0x00; /* D[7:6] 10 YUV2(=YUYV), 01 VYUY, 00 UYVY, 11 YVYU / 00 RGB 555, 01 RGB 565 */ 81572b676d7Smrg misc0 = 0x40; /* D[6]: 1 = YUV, 0 = RGB */ 81672b676d7Smrg misc4 = 0x00; /* D[1:0] 00 RGB 555, 01 YUV 422, 10 RGB 565; D[2] 1 = YUV420 mode */ 81772b676d7Smrg misc1 = 0xff; 81872b676d7Smrg break; 81972b676d7Smrg case PIXEL_FMT_YUY2: /* V/530 V/6326 */ 82072b676d7Smrg fmt = 0x80; /* D[7:6] 10 YUV2(=YUYV), 01 VYUY, 00 UYVY, 11 YVYU / 00 RGB 555, 01 RGB 565 */ 82172b676d7Smrg misc0 = 0x40; /* D[6]: 1 = YUV, 0 = RGB */ 82272b676d7Smrg misc4 = 0x00; /* D[1:0] 00 RGB 555, 01 YUV 422, 10 RGB 565; D[2] 1 = YUV420 mode */ 82372b676d7Smrg misc1 = 0xff; 82472b676d7Smrg break; 82572b676d7Smrg case PIXEL_FMT_RGB6: /* V/530 V/6326 */ 82672b676d7Smrg fmt = 0x40; /* D[7:6] 10 YUV2(=YUYV), 01 VYUY, 00 UYVY, 11 YVYU / 00 RGB 555, 01 RGB 565 */ 82772b676d7Smrg misc0 = 0x00; /* D[6]: 1 = YUV, 0 = RGB */ 82872b676d7Smrg misc4 = 0xff; 82972b676d7Smrg misc1 = 0x00; /* D[2] = Capture format selection (DS5597) - WDR sets this */ 83072b676d7Smrg break; 83172b676d7Smrg case PIXEL_FMT_RGB5: /* V/530 V/6326 */ 83272b676d7Smrg default: 83372b676d7Smrg fmt = 0x00; /* D[7:6] 10 YUV2(=YUYV), 01 VYUY, 00 UYVY, 11 YVYU / 00 RGB 555, 01 RGB 565 */ 83472b676d7Smrg misc0 = 0x00; /* D[6]: 1 = YUV, 0 = RGB */ 83572b676d7Smrg misc4 = 0xff; 83672b676d7Smrg misc1 = 0x04; /* D[2] = Capture format selection (DS5597) - WDR sets this */ 83772b676d7Smrg break; 83872b676d7Smrg } 83972b676d7Smrg 84072b676d7Smrg setvideoregmask(pSiS, Index_VI6326_VideoFormatSelect, fmt, 0xC0); 84172b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Control_Misc0, misc0, 0x40); 84272b676d7Smrg if(misc4 == 0xff) { 84372b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Control_Misc1, misc1, 0x04); 84472b676d7Smrg if(pSiS->oldChipset >= OC_SIS5597) { 84572b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Control_Misc4, 0x00, 0x05); 84672b676d7Smrg } 84772b676d7Smrg } else { 84872b676d7Smrg if(pSiS->oldChipset >= OC_SIS5597) { 84972b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Control_Misc4, misc4, 0x05); 85072b676d7Smrg } 85172b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Control_Misc1, 0x00, 0x04); 85272b676d7Smrg } 85372b676d7Smrg} 85472b676d7Smrg 85572b676d7Smrgstatic void 85672b676d7Smrgset_colorkey(SISPtr pSiS, CARD32 colorkey) 85772b676d7Smrg{ 85872b676d7Smrg CARD8 r, g, b, s; 85972b676d7Smrg 86072b676d7Smrg b = (CARD8)(colorkey & 0xFF); 86172b676d7Smrg g = (CARD8)((colorkey >> 8) & 0xFF); 86272b676d7Smrg r = (CARD8)((colorkey >> 16) & 0xFF); 86372b676d7Smrg 86472b676d7Smrg if(pSiS->CurrentLayout.bitsPerPixel >= 24) { 86572b676d7Smrg s = b; 86672b676d7Smrg b = r; 86772b676d7Smrg r = s; 86872b676d7Smrg } 86972b676d7Smrg 87072b676d7Smrg setvideoreg(pSiS, Index_VI6326_Overlay_ColorKey_Blue_Min ,(CARD8)b); 87172b676d7Smrg setvideoreg(pSiS, Index_VI6326_Overlay_ColorKey_Green_Min ,(CARD8)g); 87272b676d7Smrg setvideoreg(pSiS, Index_VI6326_Overlay_ColorKey_Red_Min ,(CARD8)r); 87372b676d7Smrg 87472b676d7Smrg setvideoreg(pSiS, Index_VI6326_Overlay_ColorKey_Blue_Max ,(CARD8)b); 87572b676d7Smrg setvideoreg(pSiS, Index_VI6326_Overlay_ColorKey_Green_Max ,(CARD8)g); 87672b676d7Smrg setvideoreg(pSiS, Index_VI6326_Overlay_ColorKey_Red_Max ,(CARD8)r); 87772b676d7Smrg} 87872b676d7Smrg 87972b676d7Smrgstatic __inline void 88072b676d7Smrgset_brightness(SISPtr pSiS, CARD8 brightness) 88172b676d7Smrg{ 88272b676d7Smrg setvideoreg(pSiS, Index_VI6326_Brightness, brightness); 88372b676d7Smrg} 88472b676d7Smrg 88572b676d7Smrgstatic __inline void 88672b676d7Smrgset_contrast(SISPtr pSiS, CARD8 contrast) 88772b676d7Smrg{ 88872b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Contrast_Enh_Ctrl, contrast, 0x07); 88972b676d7Smrg} 89072b676d7Smrg 89172b676d7Smrgstatic void 89272b676d7Smrgset_contrast_data(SISPtr pSiS, int value) 89372b676d7Smrg{ 89472b676d7Smrg unsigned long temp; 89572b676d7Smrg 89672b676d7Smrg if(value < 10000) temp = 0; 89772b676d7Smrg else temp = (value - 10000) / 20000; 89872b676d7Smrg if(temp > 3) temp = 3; 89972b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Contrast_Enh_Ctrl, (temp << 6), 0xC0); 90072b676d7Smrg switch(temp) { 90172b676d7Smrg case 0: temp = 2048; break; 90272b676d7Smrg case 1: temp = 4096; break; 90372b676d7Smrg case 2: temp = 8192; break; 90472b676d7Smrg case 3: temp = 16384; break; 90572b676d7Smrg } 90672b676d7Smrg temp <<= 10; 90772b676d7Smrg temp /= value; 90872b676d7Smrg setvideoreg(pSiS, Index_VI6326_Contrast_Factor, temp); 90972b676d7Smrg} 91072b676d7Smrg 91172b676d7Smrgstatic __inline void 91272b676d7Smrgset_disablegfx(SISPtr pSiS, Bool mybool) 91372b676d7Smrg{ 91472b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Control_Misc0, mybool ? 0x10 : 0x00, 0x10); 91572b676d7Smrg} 91672b676d7Smrg 91772b676d7Smrgstatic void 91872b676d7Smrgset_overlay(SISPtr pSiS, SISOverlayPtr pOverlay, SISPortPrivPtr pPriv, int index) 91972b676d7Smrg{ 92072b676d7Smrg ScrnInfoPtr pScrn = pSiS->pScrn; 92172b676d7Smrg 92272b676d7Smrg CARD16 pitch=0; 92372b676d7Smrg CARD8 h_over=0, v_over=0; 92472b676d7Smrg CARD16 top, bottom, left, right; 92572b676d7Smrg CARD16 screenX = pSiS->CurrentLayout.mode->HDisplay; 92672b676d7Smrg CARD16 screenY = pSiS->CurrentLayout.mode->VDisplay; 92772b676d7Smrg CARD32 watchdog; 92872b676d7Smrg 92972b676d7Smrg top = pOverlay->dstBox.y1; 93072b676d7Smrg bottom = pOverlay->dstBox.y2; 93172b676d7Smrg if(bottom > screenY) { 93272b676d7Smrg bottom = screenY; 93372b676d7Smrg } 93472b676d7Smrg 93572b676d7Smrg left = pOverlay->dstBox.x1; 93672b676d7Smrg right = pOverlay->dstBox.x2; 93772b676d7Smrg if(right > screenX) { 93872b676d7Smrg right = screenX; 93972b676d7Smrg } 94072b676d7Smrg 94172b676d7Smrg /* TW: DoubleScan modes require Y coordinates * 2 */ 94272b676d7Smrg if(pSiS->CurrentLayout.mode->Flags & V_DBLSCAN) { 94372b676d7Smrg top <<= 1; 94472b676d7Smrg bottom <<= 1; 94572b676d7Smrg } 94672b676d7Smrg /* TW: Interlace modes require Y coordinates / 2 */ 94772b676d7Smrg if(pSiS->CurrentLayout.mode->Flags & V_INTERLACE) { 94872b676d7Smrg top >>= 1; 94972b676d7Smrg bottom >>= 1; 95072b676d7Smrg } 95172b676d7Smrg 95272b676d7Smrg h_over = (((left>>8) & 0x07) | ((right>>4) & 0x70)); 95372b676d7Smrg v_over = (((top>>8) & 0x07) | ((bottom>>4) & 0x70)); 95472b676d7Smrg 95572b676d7Smrg pitch = pOverlay->pitch * pOverlay->PitchMult; 95672b676d7Smrg pitch >>= 2; /* Datasheet: Unit = double word - verified */ 95772b676d7Smrg if(pitch > 0xfff) { 95872b676d7Smrg pitch = pOverlay->pitch * (0xFFF * 2 / pOverlay->pitch); 95972b676d7Smrg pOverlay->VUSF = 0x3F; 96072b676d7Smrg } 96172b676d7Smrg 96272b676d7Smrg /* set color key */ 96372b676d7Smrg set_colorkey(pSiS, pPriv->colorKey); 96472b676d7Smrg 96572b676d7Smrg /* set color key mode */ 96672b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Key_Overlay_OP, pOverlay->keyOP, 0x0f); 96772b676d7Smrg 96872b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Control_Misc0, 0x00, 0x0c); 96972b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Control_Misc0, 0x00, 0x18); 97072b676d7Smrg 97172b676d7Smrg /* Set Y buf pitch */ /* Datasheet: Unit = double word - verified */ 97272b676d7Smrg setvideoreg(pSiS, Index_VI6326_Disp_Y_Buf_Pitch_Low, (CARD8)(pitch)); 97372b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Disp_Y_Buf_Pitch_High, (CARD8)(pitch>>8), 0x0f); 97472b676d7Smrg /* Set U/V pitch if using planar formats */ 97572b676d7Smrg if( (pOverlay->pixelFormat == PIXEL_FMT_YV12) || 97672b676d7Smrg (pOverlay->pixelFormat == PIXEL_FMT_I420) ) { 97772b676d7Smrg /* Set U/V pitch */ /* Datasheet: Unit = double word - verified */ 97872b676d7Smrg setvideoreg(pSiS, Index_VI6326_Disp_UV_Buf_Pitch_Low, (CARD8)pitch >> 1); 97972b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Disp_UV_Buf_Pitch_High, (CARD8)(pitch >> 9), 0x0f); 98072b676d7Smrg } 98172b676d7Smrg 98272b676d7Smrg /* set line buffer size */ 98372b676d7Smrg setvideoreg(pSiS, Index_VI6326_Line_Buffer_Size, pOverlay->lineBufSize); 98472b676d7Smrg 98572b676d7Smrg /* set scale factor */ 98672b676d7Smrg setvideoreg(pSiS, Index_VI6326_Hor_Scale, (CARD8)((pOverlay->HUSF) | 0xC0)); 98772b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Hor_Scale_Integer, (CARD8)(pOverlay->HIntBit), 0x0F); 98872b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Ver_Scale, (CARD8)(pOverlay->VUSF), 0x3F); 98972b676d7Smrg 99072b676d7Smrg /* TW: We don't have to wait for vertical retrace in all cases */ 99172b676d7Smrg if(pPriv->mustwait) { 99272b676d7Smrg watchdog = WATCHDOG_DELAY; 99372b676d7Smrg while ((!pOverlay->VBlankActiveFunc(pSiS)) && --watchdog); 99472b676d7Smrg if(!watchdog) xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 99572b676d7Smrg "Xv: Waiting for vertical retrace timed-out\n"); 99672b676d7Smrg } 99772b676d7Smrg 99872b676d7Smrg /* set destination window position */ 99972b676d7Smrg setvideoreg(pSiS, Index_VI6326_Win_Hor_Disp_Start_Low, (CARD8)left); 100072b676d7Smrg setvideoreg(pSiS, Index_VI6326_Win_Hor_Disp_End_Low, (CARD8)right); 100172b676d7Smrg setvideoreg(pSiS, Index_VI6326_Win_Hor_Over, (CARD8)h_over); 100272b676d7Smrg 100372b676d7Smrg setvideoreg(pSiS, Index_VI6326_Win_Ver_Disp_Start_Low, (CARD8)top); 100472b676d7Smrg setvideoreg(pSiS, Index_VI6326_Win_Ver_Disp_End_Low, (CARD8)bottom); 100572b676d7Smrg setvideoreg(pSiS, Index_VI6326_Win_Ver_Over, (CARD8)v_over); 100672b676d7Smrg 100772b676d7Smrg /* Set Y start address */ 100872b676d7Smrg setvideoreg(pSiS, Index_VI6326_Disp_Y_Buf_Start_Low, (CARD8)(pOverlay->PSY)); 100972b676d7Smrg setvideoreg(pSiS, Index_VI6326_Disp_Y_Buf_Start_Middle, (CARD8)((pOverlay->PSY)>>8)); 101072b676d7Smrg if(pSiS->oldChipset <= OC_SIS6326) { /* all old chipsets incl 6326 */ 101172b676d7Smrg /* Set overflow bits */ 101272b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Disp_Capt_Y_Buf_Start_High, 101372b676d7Smrg (CARD8)(((pOverlay->PSY)>>12) & 0xF0), 0xF0); 101472b676d7Smrg /* Set framebuffer end address */ 101572b676d7Smrg setvideoreg(pSiS, Index_VI6326_Disp_Y_End, (CARD8)(pOverlay->YUVEnd)); 101672b676d7Smrg } else { /* 530/620 */ 101772b676d7Smrg /* Set overflow bits */ 101872b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Disp_Capt_Y_Buf_Start_High, 101972b676d7Smrg (CARD8)(((pOverlay->PSY)>>13) & 0xF8), 0xF8); 102072b676d7Smrg } 102172b676d7Smrg 102272b676d7Smrg /* Set U/V start addresses if using plane formats */ 102372b676d7Smrg if( (pOverlay->pixelFormat == PIXEL_FMT_YV12) || 102472b676d7Smrg (pOverlay->pixelFormat == PIXEL_FMT_I420) ) { 102572b676d7Smrg 102672b676d7Smrg CARD32 PSU = pOverlay->PSU; 102772b676d7Smrg CARD32 PSV = pOverlay->PSV; 102872b676d7Smrg 102972b676d7Smrg /* set U/V start address */ 103072b676d7Smrg setvideoreg(pSiS, Index_VI6326_U_Buf_Start_Low, (CARD8)PSU); 103172b676d7Smrg setvideoreg(pSiS, Index_VI6326_U_Buf_Start_Middle,(CARD8)(PSU >> 8)); 103272b676d7Smrg 103372b676d7Smrg setvideoreg(pSiS, Index_VI6326_V_Buf_Start_Low, (CARD8)PSV); 103472b676d7Smrg setvideoreg(pSiS, Index_VI6326_V_Buf_Start_Middle,(CARD8)(PSV >> 8)); 103572b676d7Smrg 103672b676d7Smrg setvideoreg(pSiS, Index_VI6326_UV_Buf_Start_High, 103772b676d7Smrg (CARD8)(((PSU >> 16) & 0x0F) | ((PSV >> 12) & 0xF0)) ); 103872b676d7Smrg 103972b676d7Smrg if(pSiS->oldChipset > OC_SIS6326) { 104072b676d7Smrg /* Set bit 20 of the addresses in Misc5 (530/620 only) */ 104172b676d7Smrg setvideoreg(pSiS, Index_VI6326_Control_Misc5, 104272b676d7Smrg (CARD8)(((PSU >> (20-1)) & 0x02) | ((PSV >> (20-2)) & 0x04)) ); 104372b676d7Smrg } 104472b676d7Smrg } 104572b676d7Smrg 104672b676d7Smrg /* set brightness and contrast */ 104772b676d7Smrg set_brightness(pSiS, pPriv->brightness); 104872b676d7Smrg if(pSiS->oldChipset > OC_SIS6205C) { 104972b676d7Smrg set_contrast_data(pSiS, (pOverlay->dstBox.x2 - pOverlay->dstBox.x1) * 105072b676d7Smrg (pOverlay->dstBox.y2 - pOverlay->dstBox.y1)); 105172b676d7Smrg set_contrast(pSiS, pPriv->contrast); 105272b676d7Smrg } 105372b676d7Smrg 105472b676d7Smrg /* enable/disable graphics display around overlay */ 105572b676d7Smrg set_disablegfx(pSiS, pPriv->disablegfx); 105672b676d7Smrg 105772b676d7Smrg /* set format */ 105872b676d7Smrg set_format(pSiS, pOverlay); 105972b676d7Smrg} 106072b676d7Smrg 106172b676d7Smrg/* Overlay MUST NOT be switched off while beam is over it */ 106272b676d7Smrgstatic void 106372b676d7Smrgclose_overlay(SISPtr pSiS, SISPortPrivPtr pPriv) 106472b676d7Smrg{ 106572b676d7Smrg CARD32 watchdog; 106672b676d7Smrg 106772b676d7Smrg watchdog = WATCHDOG_DELAY; 106872b676d7Smrg while((!vblank_active_CRT1(pSiS)) && --watchdog); 106972b676d7Smrg if(pSiS->oldChipset > OC_SIS6326) { 107072b676d7Smrg /* what is this? */ 107172b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Control_Misc4, 0x40, 0x40); 107272b676d7Smrg } 107372b676d7Smrg /* disable overlay */ 107472b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Control_Misc0, 0x00, 0x02); 107572b676d7Smrg} 107672b676d7Smrg 107772b676d7Smrgstatic void 107872b676d7SmrgSIS6326DisplayVideo(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) 107972b676d7Smrg{ 108072b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 108172b676d7Smrg 108272b676d7Smrg short srcPitch = pPriv->srcPitch; 108372b676d7Smrg short height = pPriv->height; 108472b676d7Smrg short width = pPriv->width; 108572b676d7Smrg SISOverlayRec overlay; 108672b676d7Smrg int srcOffsetX=0, srcOffsetY=0; 108772b676d7Smrg int sx, sy; 108872b676d7Smrg int index = 0; 108972b676d7Smrg int pitch; 109072b676d7Smrg 109172b676d7Smrg memset(&overlay, 0, sizeof(overlay)); 109272b676d7Smrg overlay.pixelFormat = pPriv->id; 109372b676d7Smrg overlay.pitch = srcPitch; 109472b676d7Smrg overlay.keyOP = VI6326_ROP_DestKey; /* DestKey mode */ 109572b676d7Smrg 109672b676d7Smrg overlay.dstBox.x1 = pPriv->drw_x - pScrn->frameX0; 109772b676d7Smrg overlay.dstBox.x2 = pPriv->drw_x + pPriv->drw_w - pScrn->frameX0; 109872b676d7Smrg overlay.dstBox.y1 = pPriv->drw_y - pScrn->frameY0; 109972b676d7Smrg overlay.dstBox.y2 = pPriv->drw_y + pPriv->drw_h - pScrn->frameY0; 110072b676d7Smrg 110172b676d7Smrg if((overlay.dstBox.x1 > overlay.dstBox.x2) || 110272b676d7Smrg (overlay.dstBox.y1 > overlay.dstBox.y2)) 110372b676d7Smrg return; 110472b676d7Smrg 110572b676d7Smrg if((overlay.dstBox.x2 < 0) || (overlay.dstBox.y2 < 0)) 110672b676d7Smrg return; 110772b676d7Smrg 110872b676d7Smrg if(overlay.dstBox.x1 < 0) { 110972b676d7Smrg srcOffsetX = pPriv->src_w * (-overlay.dstBox.x1) / pPriv->drw_w; 111072b676d7Smrg overlay.dstBox.x1 = 0; 111172b676d7Smrg } 111272b676d7Smrg if(overlay.dstBox.y1 < 0) { 111372b676d7Smrg srcOffsetY = pPriv->src_h * (-overlay.dstBox.y1) / pPriv->drw_h; 111472b676d7Smrg overlay.dstBox.y1 = 0; 111572b676d7Smrg } 111672b676d7Smrg 111772b676d7Smrg switch(pPriv->id){ 111872b676d7Smrg case PIXEL_FMT_YV12: 111972b676d7Smrg sx = (pPriv->src_x + srcOffsetX) & ~7; 112072b676d7Smrg sy = (pPriv->src_y + srcOffsetY) & ~1; 112172b676d7Smrg pitch = (width + 3) & ~3; 112272b676d7Smrg overlay.PSY = pPriv->bufAddr[pPriv->currentBuf] + sx + sy * pitch; 112372b676d7Smrg overlay.PSV = overlay.PSY + pitch * height; 112472b676d7Smrg overlay.PSU = overlay.PSV + ((((width >> 1) + 3) & ~3) * (height >> 1)); 112572b676d7Smrg overlay.PSY >>= 2; 112672b676d7Smrg overlay.PSV >>= 2; 112772b676d7Smrg overlay.PSU >>= 2; 112872b676d7Smrg break; 112972b676d7Smrg case PIXEL_FMT_I420: 113072b676d7Smrg sx = (pPriv->src_x + srcOffsetX) & ~7; 113172b676d7Smrg sy = (pPriv->src_y + srcOffsetY) & ~1; 113272b676d7Smrg pitch = (width + 3) & ~3; 113372b676d7Smrg overlay.PSY = pPriv->bufAddr[pPriv->currentBuf] + sx + sy * pitch; 113472b676d7Smrg overlay.PSU = overlay.PSY + pitch * height; 113572b676d7Smrg overlay.PSV = overlay.PSU + ((((width >> 1) + 3) & ~3) * (height >> 1)); 113672b676d7Smrg overlay.PSY >>= 2; 113772b676d7Smrg overlay.PSV >>= 2; 113872b676d7Smrg overlay.PSU >>= 2; 113972b676d7Smrg break; 114072b676d7Smrg case PIXEL_FMT_YUY2: 114172b676d7Smrg case PIXEL_FMT_UYVY: 114272b676d7Smrg case PIXEL_FMT_RGB6: 114372b676d7Smrg case PIXEL_FMT_RGB5: 114472b676d7Smrg default: 114572b676d7Smrg sx = (pPriv->src_x + srcOffsetX) & ~1; 114672b676d7Smrg sy = (pPriv->src_y + srcOffsetY); 114772b676d7Smrg overlay.PSY = (pPriv->bufAddr[pPriv->currentBuf] + sx*2 + sy*srcPitch); 114872b676d7Smrg overlay.PSY >>= 2; 114972b676d7Smrg break; 115072b676d7Smrg } 115172b676d7Smrg 115272b676d7Smrg /* FIXME: Is this correct? (Is it required to set the end address? 115372b676d7Smrg * Datasheet is not clear) - (reg does not exist on 530/620) 115472b676d7Smrg */ 115572b676d7Smrg overlay.YUVEnd = (pPriv->bufAddr[pPriv->currentBuf] + pPriv->totalSize) >> 14; 115672b676d7Smrg 115772b676d7Smrg /* FIXME: is it possible that srcW < 0 */ 115872b676d7Smrg overlay.srcW = pPriv->src_w - (sx - pPriv->src_x); 115972b676d7Smrg overlay.srcH = pPriv->src_h - (sy - pPriv->src_y); 116072b676d7Smrg 116172b676d7Smrg if( (pPriv->oldx1 != overlay.dstBox.x1) || 116272b676d7Smrg (pPriv->oldx2 != overlay.dstBox.x2) || 116372b676d7Smrg (pPriv->oldy1 != overlay.dstBox.y1) || 116472b676d7Smrg (pPriv->oldy2 != overlay.dstBox.y2) ) { 116572b676d7Smrg pPriv->mustwait = 1; 116672b676d7Smrg pPriv->oldx1 = overlay.dstBox.x1; pPriv->oldx2 = overlay.dstBox.x2; 116772b676d7Smrg pPriv->oldy1 = overlay.dstBox.y1; pPriv->oldy2 = overlay.dstBox.y2; 116872b676d7Smrg } 116972b676d7Smrg 117072b676d7Smrg /* calculate line buffer length */ 117172b676d7Smrg calc_line_buf_size(&overlay); 117272b676d7Smrg 117372b676d7Smrg overlay.VBlankActiveFunc = vblank_active_CRT1; 117472b676d7Smrg/* overlay.GetScanLineFunc = get_scanline_CRT1; */ 117572b676d7Smrg 117672b676d7Smrg /* calculate scale factor */ 117772b676d7Smrg calc_scale_factor(pSiS, &overlay, pScrn, pPriv); 117872b676d7Smrg 117972b676d7Smrg /* set (not only determine) if line buffer is to be merged */ 118072b676d7Smrg if(pSiS->oldChipset > OC_SIS5597) { 118172b676d7Smrg int temp = 384; 118272b676d7Smrg if(pSiS->oldChipset <= OC_SIS6326) temp = 352; 118372b676d7Smrg merge_line_buf(pSiS, pPriv, (overlay.srcW > temp)); 118472b676d7Smrg } 118572b676d7Smrg 118672b676d7Smrg /* set overlay */ 118772b676d7Smrg set_overlay(pSiS, &overlay, pPriv, index); 118872b676d7Smrg 118972b676d7Smrg /* enable overlay */ 119072b676d7Smrg if(pSiS->oldChipset > OC_SIS6326) { 119172b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Control_Misc4, 0x40, 0x40); 119272b676d7Smrg } 119372b676d7Smrg setvideoregmask(pSiS, Index_VI6326_Control_Misc0, 0x02, 0x02); 119472b676d7Smrg 119572b676d7Smrg pPriv->mustwait = 0; 119672b676d7Smrg} 119772b676d7Smrg 119872b676d7Smrgstatic void 119972b676d7SmrgSIS6326StopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown) 120072b676d7Smrg{ 120172b676d7Smrg SISPortPrivPtr pPriv = (SISPortPrivPtr)data; 120272b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 120372b676d7Smrg 120472b676d7Smrg if(pPriv->grabbedByV4L) return; 120572b676d7Smrg 120672b676d7Smrg REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 120772b676d7Smrg 120872b676d7Smrg if(shutdown) { 120972b676d7Smrg if(pPriv->videoStatus & CLIENT_VIDEO_ON) { 121072b676d7Smrg close_overlay(pSiS, pPriv); 121172b676d7Smrg pPriv->mustwait = 1; 121272b676d7Smrg } 121372b676d7Smrg SISFreeFBMemory(pScrn, &pPriv->handle); 121472b676d7Smrg pPriv->videoStatus = 0; 121572b676d7Smrg pSiS->VideoTimerCallback = NULL; 121672b676d7Smrg } else { 121772b676d7Smrg if(pPriv->videoStatus & CLIENT_VIDEO_ON) { 121872b676d7Smrg pPriv->videoStatus = OFF_TIMER | CLIENT_VIDEO_ON; 121972b676d7Smrg pPriv->offTime = currentTime.milliseconds + OFF_DELAY; 122072b676d7Smrg pSiS->VideoTimerCallback = SIS6326VideoTimerCallback; 122172b676d7Smrg } 122272b676d7Smrg } 122372b676d7Smrg} 122472b676d7Smrg 122572b676d7Smrgstatic int 122672b676d7SmrgSIS6326PutImage( 122772b676d7Smrg ScrnInfoPtr pScrn, 122872b676d7Smrg short src_x, short src_y, 122972b676d7Smrg short drw_x, short drw_y, 123072b676d7Smrg short src_w, short src_h, 123172b676d7Smrg short drw_w, short drw_h, 123272b676d7Smrg int id, unsigned char* buf, 123372b676d7Smrg short width, short height, 123472b676d7Smrg Bool sync, 123572b676d7Smrg RegionPtr clipBoxes, pointer data, 123672b676d7Smrg DrawablePtr pDraw 123772b676d7Smrg){ 123872b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 123972b676d7Smrg SISPortPrivPtr pPriv = (SISPortPrivPtr)data; 124072b676d7Smrg int totalSize=0; 124172b676d7Smrg CARD32 *src, *dest; 124272b676d7Smrg unsigned long i; 124372b676d7Smrg 124472b676d7Smrg if(pPriv->grabbedByV4L) return Success; 124572b676d7Smrg 124672b676d7Smrg pPriv->drw_x = drw_x; 124772b676d7Smrg pPriv->drw_y = drw_y; 124872b676d7Smrg pPriv->drw_w = drw_w; 124972b676d7Smrg pPriv->drw_h = drw_h; 125072b676d7Smrg pPriv->src_x = src_x; 125172b676d7Smrg pPriv->src_y = src_y; 125272b676d7Smrg pPriv->src_w = src_w; 125372b676d7Smrg pPriv->src_h = src_h; 125472b676d7Smrg pPriv->id = id; 125572b676d7Smrg pPriv->height = height; 125672b676d7Smrg pPriv->width = width; 125772b676d7Smrg 125872b676d7Smrg /* Pixel formats: 125972b676d7Smrg 1. YU12: 3 planes: H V 126072b676d7Smrg Y sample period 1 1 (8 bit per pixel) 126172b676d7Smrg V sample period 2 2 (8 bit per pixel, subsampled) 126272b676d7Smrg U sample period 2 2 (8 bit per pixel, subsampled) 126372b676d7Smrg 126472b676d7Smrg Y plane is fully sampled (width*height), U and V planes 126572b676d7Smrg are sampled in 2x2 blocks, hence a group of 4 pixels requires 126672b676d7Smrg 4 + 1 + 1 = 6 bytes. The data is planar, ie in single planes 126772b676d7Smrg for Y, U and V. 126872b676d7Smrg 2. UYVY: 3 planes: H V 126972b676d7Smrg Y sample period 1 1 (8 bit per pixel) 127072b676d7Smrg V sample period 2 1 (8 bit per pixel, subsampled) 127172b676d7Smrg U sample period 2 1 (8 bit per pixel, subsampled) 127272b676d7Smrg Y plane is fully sampled (width*height), U and V planes 127372b676d7Smrg are sampled in 2x1 blocks, hence a group of 4 pixels requires 127472b676d7Smrg 4 + 2 + 2 = 8 bytes. The data is bit packed, there are no separate 127572b676d7Smrg Y, U or V planes. 127672b676d7Smrg Bit order: U0 Y0 V0 Y1 U2 Y2 V2 Y3 ... 127772b676d7Smrg 3. I420: Like YU12, but planes U and V are in reverse order. 127872b676d7Smrg 4. YUY2: Like UYVY, but order is 127972b676d7Smrg Y0 U0 Y1 V0 Y2 U2 Y3 V2 ... 128072b676d7Smrg */ 128172b676d7Smrg 128272b676d7Smrg switch(id){ 128372b676d7Smrg case PIXEL_FMT_YV12: 128472b676d7Smrg case PIXEL_FMT_I420: 128572b676d7Smrg pPriv->srcPitch = (width + 7) & ~7; 128672b676d7Smrg /* Size = width * height * 3 / 2 */ 128772b676d7Smrg totalSize = (pPriv->srcPitch * height * 3) >> 1; 128872b676d7Smrg break; 128972b676d7Smrg case PIXEL_FMT_YUY2: 129072b676d7Smrg case PIXEL_FMT_UYVY: 129172b676d7Smrg case PIXEL_FMT_RGB5: 129272b676d7Smrg case PIXEL_FMT_RGB6: 129372b676d7Smrg default: 129472b676d7Smrg pPriv->srcPitch = ((width << 1) + 3) & ~3; 129572b676d7Smrg /* Size = width * 2 * height */ 129672b676d7Smrg totalSize = pPriv->srcPitch * height; 129772b676d7Smrg } 129872b676d7Smrg 129972b676d7Smrg /* make it a multiple of 16 to simplify to copy loop */ 130072b676d7Smrg totalSize += 15; 130172b676d7Smrg totalSize &= ~15; /* in bytes */ 130272b676d7Smrg 130372b676d7Smrg pPriv->totalSize = totalSize; 130472b676d7Smrg 130572b676d7Smrg /* allocate memory (we do doublebuffering) - size is in bytes */ 130672b676d7Smrg if(!(pPriv->bufAddr[0] = SISAllocateFBMemory(pScrn, &pPriv->handle, totalSize << 1))) 130772b676d7Smrg return BadAlloc; 130872b676d7Smrg 130972b676d7Smrg pPriv->bufAddr[1] = pPriv->bufAddr[0] + totalSize; 131072b676d7Smrg 131172b676d7Smrg /* copy data */ 131272b676d7Smrg if((pSiS->XvUseMemcpy) || (totalSize < 16)) { 131372b676d7Smrg SiSMemCopyToVideoRam(pSiS, pSiS->FbBase + pPriv->bufAddr[pPriv->currentBuf], buf, totalSize); 131472b676d7Smrg } else { 131572b676d7Smrg dest = (CARD32 *)(pSiS->FbBase + pPriv->bufAddr[pPriv->currentBuf]); 131672b676d7Smrg src = (CARD32 *)buf; 131772b676d7Smrg for(i = 0; i < (totalSize/16); i++) { 131872b676d7Smrg *dest++ = *src++; 131972b676d7Smrg *dest++ = *src++; 132072b676d7Smrg *dest++ = *src++; 132172b676d7Smrg *dest++ = *src++; 132272b676d7Smrg } 132372b676d7Smrg } 132472b676d7Smrg 132572b676d7Smrg SIS6326DisplayVideo(pScrn, pPriv); 132672b676d7Smrg 132772b676d7Smrg /* update cliplist */ 132872b676d7Smrg if( pPriv->autopaintColorKey && 132972b676d7Smrg (pPriv->grabbedByV4L || 133072b676d7Smrg#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,3,99,3,0) 133172b676d7Smrg !RegionsEqual(&pPriv->clip, clipBoxes)) ) { 133272b676d7Smrg#else 133372b676d7Smrg !REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) ) { 133472b676d7Smrg#endif 133572b676d7Smrg /* We always paint colorkey for V4L */ 133672b676d7Smrg if(!pPriv->grabbedByV4L) 133772b676d7Smrg REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes); 133872b676d7Smrg /* draw these */ 133972b676d7Smrg#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,1,99,1,0) 134072b676d7Smrg (*pSiS->AccelInfoPtr->FillSolidRects)(pScrn, pPriv->colorKey, GXcopy, ~0, 134172b676d7Smrg REGION_NUM_RECTS(clipBoxes), 134272b676d7Smrg REGION_RECTS(clipBoxes)); 134372b676d7Smrg#else 134472b676d7Smrg xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes); 134572b676d7Smrg#endif 134672b676d7Smrg } 134772b676d7Smrg 134872b676d7Smrg pPriv->currentBuf ^= 1; 134972b676d7Smrg 135072b676d7Smrg pPriv->videoStatus = CLIENT_VIDEO_ON; 135172b676d7Smrg 135272b676d7Smrg pSiS->VideoTimerCallback = SIS6326VideoTimerCallback; 135372b676d7Smrg 135472b676d7Smrg return Success; 135572b676d7Smrg} 135672b676d7Smrg 135772b676d7Smrgstatic int 135872b676d7SmrgSIS6326QueryImageAttributes( 135972b676d7Smrg ScrnInfoPtr pScrn, 136072b676d7Smrg int id, 136172b676d7Smrg unsigned short *w, unsigned short *h, 136272b676d7Smrg int *pitches, int *offsets 136372b676d7Smrg){ 136472b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 136572b676d7Smrg int pitchY, pitchUV; 136672b676d7Smrg int size, sizeY, sizeUV; 136772b676d7Smrg 136872b676d7Smrg if(*w < IMAGE_MIN_WIDTH) *w = IMAGE_MIN_WIDTH; 136972b676d7Smrg if(*h < IMAGE_MIN_HEIGHT) *h = IMAGE_MIN_HEIGHT; 137072b676d7Smrg 137172b676d7Smrg if(pSiS->oldChipset < OC_SIS6326) { 137272b676d7Smrg if(*w > IMAGE_MAX_WIDTH_5597) *w = IMAGE_MAX_WIDTH_5597; 137372b676d7Smrg if(*h > IMAGE_MAX_HEIGHT_5597) *h = IMAGE_MAX_HEIGHT_5597; 137472b676d7Smrg } else { 137572b676d7Smrg if(*w > IMAGE_MAX_WIDTH) *w = IMAGE_MAX_WIDTH; 137672b676d7Smrg if(*h > IMAGE_MAX_HEIGHT) *h = IMAGE_MAX_HEIGHT; 137772b676d7Smrg } 137872b676d7Smrg 137972b676d7Smrg switch(id) { 138072b676d7Smrg case PIXEL_FMT_YV12: 138172b676d7Smrg case PIXEL_FMT_I420: 138272b676d7Smrg *w = (*w + 7) & ~7; 138372b676d7Smrg *h = (*h + 1) & ~1; 138472b676d7Smrg pitchY = *w; 138572b676d7Smrg pitchUV = *w >> 1; 138672b676d7Smrg if(pitches) { 138772b676d7Smrg pitches[0] = pitchY; 138872b676d7Smrg pitches[1] = pitches[2] = pitchUV; 138972b676d7Smrg } 139072b676d7Smrg sizeY = pitchY * (*h); 139172b676d7Smrg sizeUV = pitchUV * ((*h) >> 1); 139272b676d7Smrg if(offsets) { 139372b676d7Smrg offsets[0] = 0; 139472b676d7Smrg offsets[1] = sizeY; 139572b676d7Smrg offsets[2] = sizeY + sizeUV; 139672b676d7Smrg } 139772b676d7Smrg size = sizeY + (sizeUV << 1); 139872b676d7Smrg break; 139972b676d7Smrg case PIXEL_FMT_YUY2: 140072b676d7Smrg case PIXEL_FMT_UYVY: 140172b676d7Smrg case PIXEL_FMT_RGB5: 140272b676d7Smrg case PIXEL_FMT_RGB6: 140372b676d7Smrg default: 140472b676d7Smrg *w = (*w + 1) & ~1; 140572b676d7Smrg pitchY = *w << 1; 140672b676d7Smrg if(pitches) pitches[0] = pitchY; 140772b676d7Smrg if(offsets) offsets[0] = 0; 140872b676d7Smrg size = pitchY * (*h); 140972b676d7Smrg break; 141072b676d7Smrg } 141172b676d7Smrg 141272b676d7Smrg return size; 141372b676d7Smrg} 141472b676d7Smrg 141572b676d7Smrgstatic void 141672b676d7SmrgSIS6326VideoTimerCallback(ScrnInfoPtr pScrn, Time now) 141772b676d7Smrg{ 141872b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 141972b676d7Smrg SISPortPrivPtr pPriv = NULL; 142072b676d7Smrg unsigned char sridx, cridx; 142172b676d7Smrg 142272b676d7Smrg pSiS->VideoTimerCallback = NULL; 142372b676d7Smrg 142472b676d7Smrg if(!pScrn->vtSema) return; 142572b676d7Smrg 142672b676d7Smrg if(pSiS->adaptor) { 142772b676d7Smrg pPriv = GET_PORT_PRIVATE(pScrn); 142872b676d7Smrg if(!pPriv->videoStatus) pPriv = NULL; 142972b676d7Smrg } 143072b676d7Smrg 143172b676d7Smrg if(pPriv) { 143272b676d7Smrg if(pPriv->videoStatus & TIMER_MASK) { 143372b676d7Smrg if(pPriv->videoStatus & OFF_TIMER) { 143472b676d7Smrg if(pPriv->offTime < now) { 143572b676d7Smrg /* Turn off the overlay */ 143672b676d7Smrg sridx = inSISREG(SISSR); cridx = inSISREG(SISCR); 143772b676d7Smrg close_overlay(pSiS, pPriv); 143872b676d7Smrg outSISREG(SISSR, sridx); outSISREG(SISCR, cridx); 143972b676d7Smrg pPriv->mustwait = 1; 144072b676d7Smrg pPriv->videoStatus = FREE_TIMER; 144172b676d7Smrg pPriv->freeTime = now + FREE_DELAY; 144272b676d7Smrg pSiS->VideoTimerCallback = SIS6326VideoTimerCallback; 144372b676d7Smrg } 144472b676d7Smrg } else if(pPriv->videoStatus & FREE_TIMER) { 144572b676d7Smrg if(pPriv->freeTime < now) { 144672b676d7Smrg SISFreeFBMemory(pScrn, &pPriv->handle); 144772b676d7Smrg pPriv->mustwait = 1; 144872b676d7Smrg pPriv->videoStatus = 0; 144972b676d7Smrg } 145072b676d7Smrg } else 145172b676d7Smrg pSiS->VideoTimerCallback = SIS6326VideoTimerCallback; 145272b676d7Smrg } 145372b676d7Smrg } 145472b676d7Smrg} 145572b676d7Smrg 145672b676d7Smrg/* Offscreen surface stuff for v4l */ 145772b676d7Smrg 145872b676d7Smrgstatic int 145972b676d7SmrgSIS6326AllocSurface ( 146072b676d7Smrg ScrnInfoPtr pScrn, 146172b676d7Smrg int id, 146272b676d7Smrg unsigned short w, 146372b676d7Smrg unsigned short h, 146472b676d7Smrg XF86SurfacePtr surface 146572b676d7Smrg) 146672b676d7Smrg{ 146772b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 146872b676d7Smrg SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn); 146972b676d7Smrg int size; 147072b676d7Smrg 147172b676d7Smrg if((w < IMAGE_MIN_WIDTH) || (h < IMAGE_MIN_HEIGHT)) 147272b676d7Smrg return BadValue; 147372b676d7Smrg 147472b676d7Smrg if(pSiS->oldChipset < OC_SIS6326) { 147572b676d7Smrg if((w > IMAGE_MAX_WIDTH_5597) || (h > IMAGE_MAX_HEIGHT_5597)) 147672b676d7Smrg return BadValue; 147772b676d7Smrg } else { 147872b676d7Smrg if((w > IMAGE_MAX_WIDTH) || (h > IMAGE_MAX_HEIGHT)) 147972b676d7Smrg return BadValue; 148072b676d7Smrg } 148172b676d7Smrg 148272b676d7Smrg if(pPriv->grabbedByV4L) 148372b676d7Smrg return BadAlloc; 148472b676d7Smrg 148572b676d7Smrg w = (w + 1) & ~1; 148672b676d7Smrg pPriv->pitch = ((w << 1) + 63) & ~63; /* Only packed pixel modes supported */ 148772b676d7Smrg size = h * pPriv->pitch; 148872b676d7Smrg if(!(pPriv->offset = SISAllocateFBMemory(pScrn, &pPriv->handle, size))) 148972b676d7Smrg return BadAlloc; 149072b676d7Smrg 149172b676d7Smrg pPriv->totalSize = size; 149272b676d7Smrg 149372b676d7Smrg surface->width = w; 149472b676d7Smrg surface->height = h; 149572b676d7Smrg surface->pScrn = pScrn; 149672b676d7Smrg surface->id = id; 149772b676d7Smrg surface->pitches = &pPriv->pitch; 149872b676d7Smrg surface->offsets = &pPriv->offset; 149972b676d7Smrg surface->devPrivate.ptr = (pointer)pPriv; 150072b676d7Smrg 150172b676d7Smrg close_overlay(pSiS, pPriv); 150272b676d7Smrg pPriv->videoStatus = 0; 150372b676d7Smrg REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 150472b676d7Smrg pSiS->VideoTimerCallback = NULL; 150572b676d7Smrg pPriv->grabbedByV4L = TRUE; 150672b676d7Smrg return Success; 150772b676d7Smrg} 150872b676d7Smrg 150972b676d7Smrgstatic int 151072b676d7SmrgSIS6326StopSurface (XF86SurfacePtr surface) 151172b676d7Smrg{ 151272b676d7Smrg SISPortPrivPtr pPriv = (SISPortPrivPtr)(surface->devPrivate.ptr); 151372b676d7Smrg SISPtr pSiS = SISPTR(surface->pScrn); 151472b676d7Smrg 151572b676d7Smrg if(pPriv->grabbedByV4L && pPriv->videoStatus) { 151672b676d7Smrg close_overlay(pSiS, pPriv); 151772b676d7Smrg pPriv->mustwait = 1; 151872b676d7Smrg pPriv->videoStatus = 0; 151972b676d7Smrg } 152072b676d7Smrg return Success; 152172b676d7Smrg} 152272b676d7Smrg 152372b676d7Smrgstatic int 152472b676d7SmrgSIS6326FreeSurface (XF86SurfacePtr surface) 152572b676d7Smrg{ 152672b676d7Smrg SISPortPrivPtr pPriv = (SISPortPrivPtr)(surface->devPrivate.ptr); 152772b676d7Smrg 152872b676d7Smrg if(pPriv->grabbedByV4L) { 152972b676d7Smrg SIS6326StopSurface(surface); 153072b676d7Smrg SISFreeFBMemory(surface->pScrn, &pPriv->handle); 153172b676d7Smrg pPriv->grabbedByV4L = FALSE; 153272b676d7Smrg } 153372b676d7Smrg return Success; 153472b676d7Smrg} 153572b676d7Smrg 153672b676d7Smrgstatic int 153772b676d7SmrgSIS6326GetSurfaceAttribute ( 153872b676d7Smrg ScrnInfoPtr pScrn, 153972b676d7Smrg Atom attribute, 154072b676d7Smrg INT32 *value 154172b676d7Smrg) 154272b676d7Smrg{ 154372b676d7Smrg SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn); 154472b676d7Smrg 154572b676d7Smrg return SIS6326GetPortAttribute(pScrn, attribute, value, (pointer)pPriv); 154672b676d7Smrg} 154772b676d7Smrg 154872b676d7Smrgstatic int 154972b676d7SmrgSIS6326SetSurfaceAttribute( 155072b676d7Smrg ScrnInfoPtr pScrn, 155172b676d7Smrg Atom attribute, 155272b676d7Smrg INT32 value 155372b676d7Smrg) 155472b676d7Smrg{ 155572b676d7Smrg SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);; 155672b676d7Smrg 155772b676d7Smrg return SIS6326SetPortAttribute(pScrn, attribute, value, (pointer)pPriv); 155872b676d7Smrg} 155972b676d7Smrg 156072b676d7Smrgstatic int 156172b676d7SmrgSIS6326DisplaySurface ( 156272b676d7Smrg XF86SurfacePtr surface, 156372b676d7Smrg short src_x, short src_y, 156472b676d7Smrg short drw_x, short drw_y, 156572b676d7Smrg short src_w, short src_h, 156672b676d7Smrg short drw_w, short drw_h, 156772b676d7Smrg RegionPtr clipBoxes 156872b676d7Smrg) 156972b676d7Smrg{ 157072b676d7Smrg ScrnInfoPtr pScrn = surface->pScrn; 157172b676d7Smrg SISPortPrivPtr pPriv = (SISPortPrivPtr)(surface->devPrivate.ptr); 157272b676d7Smrg 157372b676d7Smrg if(!pPriv->grabbedByV4L) 157472b676d7Smrg return Success; 157572b676d7Smrg 157672b676d7Smrg pPriv->drw_x = drw_x; 157772b676d7Smrg pPriv->drw_y = drw_y; 157872b676d7Smrg pPriv->drw_w = drw_w; 157972b676d7Smrg pPriv->drw_h = drw_h; 158072b676d7Smrg pPriv->src_x = src_x; 158172b676d7Smrg pPriv->src_y = src_y; 158272b676d7Smrg pPriv->src_w = src_w; 158372b676d7Smrg pPriv->src_h = src_h; 158472b676d7Smrg pPriv->id = surface->id; 158572b676d7Smrg pPriv->height = surface->height; 158672b676d7Smrg pPriv->bufAddr[0] = surface->offsets[0]; 158772b676d7Smrg pPriv->currentBuf = 0; 158872b676d7Smrg pPriv->srcPitch = surface->pitches[0]; 158972b676d7Smrg 159072b676d7Smrg SIS6326DisplayVideo(pScrn, pPriv); 159172b676d7Smrg 159272b676d7Smrg if(pPriv->autopaintColorKey) { 159372b676d7Smrg#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,1,99,1,0) 159472b676d7Smrg (*XAAPTR(pScrn)->FillSolidRects)(pScrn, pPriv->colorKey, GXcopy, ~0, 159572b676d7Smrg REGION_NUM_RECTS(clipBoxes), 159672b676d7Smrg REGION_RECTS(clipBoxes)); 159772b676d7Smrg#else 159872b676d7Smrg xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes); 159972b676d7Smrg#endif 160072b676d7Smrg } 160172b676d7Smrg 160272b676d7Smrg pPriv->videoStatus = CLIENT_VIDEO_ON; 160372b676d7Smrg 160472b676d7Smrg return Success; 160572b676d7Smrg} 160672b676d7Smrg 160772b676d7SmrgXF86OffscreenImageRec SIS6326OffscreenImages[2] = 160872b676d7Smrg{ 160972b676d7Smrg { 161072b676d7Smrg &SIS6326Images[0], /* YUV2 */ 161172b676d7Smrg VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, 161272b676d7Smrg SIS6326AllocSurface, 161372b676d7Smrg SIS6326FreeSurface, 161472b676d7Smrg SIS6326DisplaySurface, 161572b676d7Smrg SIS6326StopSurface, 161672b676d7Smrg SIS6326GetSurfaceAttribute, 161772b676d7Smrg SIS6326SetSurfaceAttribute, 161872b676d7Smrg IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT, 161972b676d7Smrg NUM_ATTRIBUTES, 162072b676d7Smrg &SIS6326Attributes[0] /* Support all attributes */ 162172b676d7Smrg }, 162272b676d7Smrg { 162372b676d7Smrg &SIS6326Images[1], /* UYVY */ 162472b676d7Smrg VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, 162572b676d7Smrg SIS6326AllocSurface, 162672b676d7Smrg SIS6326FreeSurface, 162772b676d7Smrg SIS6326DisplaySurface, 162872b676d7Smrg SIS6326StopSurface, 162972b676d7Smrg SIS6326GetSurfaceAttribute, 163072b676d7Smrg SIS6326SetSurfaceAttribute, 163172b676d7Smrg IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT, 163272b676d7Smrg NUM_ATTRIBUTES, 163372b676d7Smrg &SIS6326Attributes[0] /* Support all attributes */ 163472b676d7Smrg }, 163572b676d7Smrg}; 163672b676d7Smrg 163772b676d7Smrgstatic void 163872b676d7SmrgSIS6326InitOffscreenImages(ScreenPtr pScrn) 163972b676d7Smrg{ 164072b676d7Smrg xf86XVRegisterOffscreenImages(pScrn, SIS6326OffscreenImages, 2); 164172b676d7Smrg} 164272b676d7Smrg 164372b676d7Smrg 164472b676d7Smrg 164572b676d7Smrg 1646