Home | History | Annotate | Line # | Download | only in src
      1 /*
      2  * Copyright 2004-2005 The Unichrome Project  [unichrome.sf.net]
      3  * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
      4  * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sub license,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice (including the
     14  * next paragraph) shall be included in all copies or substantial portions
     15  * of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
     20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     22  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     23  * DEALINGS IN THE SOFTWARE.
     24  */
     25 
     26 #ifdef HAVE_CONFIG_H
     27 #include "config.h"
     28 #endif
     29 
     30 #include "xf86.h"
     31 #include "xf86_OSproc.h"
     32 
     33 #ifdef HAVE_DRI
     34 #include "xf86drm.h"
     35 #include "via_drmclient.h"
     36 #include "via_drm.h"
     37 #endif
     38 #include "via_driver.h"
     39 
     40 #include <math.h>
     41 #include <unistd.h>
     42 
     43 /*
     44  * Warning: this file contains revision checks which are CLE266-specific.
     45  * There seems to be no checking present for KM400 or more recent devices.
     46  *
     47  * TODO:
     48  *   - pVia->Chipset checking, of course
     49  *   - move content of pVia->HWDiff into pVia->swov
     50  *   - merge with CLEXF40040
     51  */
     52 
     53 /*
     54  * Old via_regrec code.
     55  */
     56 #define VIDREG_BUFFER_SIZE  100  /* Number of entries in the VidRegBuffer. */
     57 #define IN_VIDEO_DISPLAY (*((unsigned long volatile *)(pVia->MapBase + V_FLAGS)) & VBI_STATUS)
     58 #define VIA_FIRETIMEOUT 40000
     59 
     60 enum HQV_CME_Regs {
     61         HQV_SDO_CTRL1,
     62         HQV_SDO_CTRL2,
     63         HQV_SDO_CTRL3,
     64         HQV_SDO_CTRL4
     65 };
     66 
     67 /* register offsets for VT3553/VX800 */
     68 static const unsigned hqv_cme_regs[] = {
     69     [HQV_SDO_CTRL1]  = HQV_SRC_DATA_OFFSET_CONTROL1,
     70     [HQV_SDO_CTRL2]  = HQV_SRC_DATA_OFFSET_CONTROL2,
     71     [HQV_SDO_CTRL3]  = HQV_SRC_DATA_OFFSET_CONTROL3,
     72     [HQV_SDO_CTRL4]  = HQV_SRC_DATA_OFFSET_CONTROL4
     73 };
     74 
     75 /* register hqv offsets for new VT3409/VX855 */
     76 static const unsigned hqv_cme_regs_409[] = {
     77     [HQV_SDO_CTRL1]  = HQV_SRC_DATA_OFFSET_CTRL1_409,
     78     [HQV_SDO_CTRL2]  = HQV_SRC_DATA_OFFSET_CTRL2_409,
     79     [HQV_SDO_CTRL3]  = HQV_SRC_DATA_OFFSET_CTRL3_409,
     80     [HQV_SDO_CTRL4]  = HQV_SRC_DATA_OFFSET_CTRL4_409
     81 };
     82 
     83 #define HQV_CME_REG(HWDiff, name) (HWDiff)->HQVCmeRegs[name]
     84 
     85 static void
     86 viaWaitVideoCommandFire(VIAPtr pVia)
     87 {
     88 /*
     89  * Uncached PCI reading throughput is about 9 MB/s; so 8 bytes/loop means about
     90  * 1M loops/second.  We want to time out after 50 ms, which means 50000 loops.
     91  */
     92     unsigned count = 50000;
     93     CARD32 volatile *pdwState =
     94             (CARD32 volatile *)(pVia->MapBase + V_COMPOSE_MODE);
     95 
     96     while (--count && ((*pdwState & V1_COMMAND_FIRE)
     97                        || (*pdwState & V3_COMMAND_FIRE))) ;
     98     if (!count) {
     99         ErrorF("viaWaitVideoCommandFire: Timeout.\n");
    100     }
    101 }
    102 
    103 static void
    104 viaWaitHQVFlip(VIAPtr pVia)
    105 {
    106     unsigned long proReg = 0;
    107     CARD32 volatile *pdwState;
    108     unsigned count = 50000;
    109 
    110     if (pVia->ChipId == PCI_CHIP_VT3259
    111         && !(pVia->swov.gdwVideoFlagSW & VIDEO_1_INUSE))
    112         proReg = PRO_HQV1_OFFSET;
    113 
    114     pdwState = (CARD32 volatile *)(pVia->MapBase + (HQV_CONTROL + proReg));
    115 
    116     if (pVia->VideoEngine == VIDEO_ENGINE_CME) {
    117 		while (--count && (*pdwState & HQV_SUBPIC_FLIP));
    118     } else {
    119         while (--count && !(*pdwState & HQV_FLIP_STATUS)) ;
    120     }
    121 }
    122 
    123 static void
    124 viaWaitHQVFlipClear(VIAPtr pVia, unsigned long dwData)
    125 {
    126     CARD32 volatile *pdwState =
    127             (CARD32 volatile *)(pVia->MapBase + HQV_CONTROL);
    128     *pdwState = dwData;
    129     unsigned count = 50000;
    130 
    131     while (--count && (*pdwState & HQV_FLIP_STATUS)) {
    132         VIASETREG(HQV_CONTROL, *pdwState | HQV_FLIP_STATUS);
    133     }
    134 }
    135 
    136 static void
    137 viaWaitVBI(VIAPtr pVia)
    138 {
    139     while (IN_VIDEO_DISPLAY) ;
    140 }
    141 
    142 static void
    143 viaWaitHQVDone(VIAPtr pVia)
    144 {
    145     CARD32 volatile *pdwState;
    146     unsigned long proReg = 0;
    147     unsigned count = 50000;
    148 
    149     if (pVia->ChipId == PCI_CHIP_VT3259
    150         && !(pVia->swov.gdwVideoFlagSW & VIDEO_1_INUSE))
    151         proReg = PRO_HQV1_OFFSET;
    152 
    153     pdwState = (CARD32 volatile *)(pVia->MapBase + (HQV_CONTROL + proReg));
    154     if (pVia->swov.MPEG_ON) {
    155         while (--count && (*pdwState & HQV_SW_FLIP)) ;
    156     }
    157 }
    158 
    159 /*
    160  * Send all data in VidRegBuffer to the hardware.
    161  */
    162 static void
    163 FlushVidRegBuffer(VIAPtr pVia)
    164 {
    165     unsigned int i;
    166 
    167     viaWaitVideoCommandFire(pVia);
    168 
    169     for (i = 0; i < pVia->VidRegCursor; i += 2) {
    170         VIASETREG(pVia->VidRegBuffer[i], pVia->VidRegBuffer[i + 1]);
    171         DBG_DD(ErrorF("FlushVideoRegs: [%i] %08lx %08lx\n",
    172                       i >> 1, pVia->VidRegBuffer[i] + 0x200,
    173                       pVia->VidRegBuffer[i + 1]));
    174     }
    175 
    176     /* BUG: (?) VIA never resets the cursor.
    177      * My fix is commented out for now, in case they had a reason for that. /A
    178      */
    179     /* pVia->VidRegCursor = 0; */
    180 }
    181 
    182 /*
    183  * Initialize and clear VidRegBuffer.
    184  */
    185 static void
    186 ResetVidRegBuffer(VIAPtr pVia)
    187 {
    188     /* BUG: (Memory leak) This allocation may need have a corresponding free somewhere... /A */
    189     if (!pVia->VidRegBuffer)
    190         pVia->VidRegBuffer =
    191                 xnfcalloc(VIDREG_BUFFER_SIZE, sizeof(CARD32) * 2);
    192     pVia->VidRegCursor = 0;
    193 }
    194 
    195 /*
    196  * Save a video register and data in VidRegBuffer.
    197  */
    198 static void
    199 SaveVideoRegister(VIAPtr pVia, CARD32 index, CARD32 data)
    200 {
    201     if (pVia->VidRegCursor >= VIDREG_BUFFER_SIZE) {
    202         DBG_DD(ErrorF("SaveVideoRegister: Out of video register space flushing"));
    203         FlushVidRegBuffer(pVia);
    204         ResetVidRegBuffer(pVia);
    205     }
    206 
    207     pVia->VidRegBuffer[pVia->VidRegCursor++] = index;
    208     pVia->VidRegBuffer[pVia->VidRegCursor++] = data;
    209 }
    210 
    211 /*
    212  * HW Difference Flag (moved here from via_hwdiff.c)
    213  *
    214  * These are the entries of HWDiff used in our code (currently):
    215  *                     CLE266Ax   CLE266Cx   KM400     K8M800    PM800
    216  * ThreeHQVBuffer      FALSE      TRUE       TRUE      TRUE      TRUE
    217  * HQVFetchByteUnit    FALSE      TRUE       TRUE      TRUE      TRUE
    218  * SupportTwoColorKey  FALSE      TRUE       FALSE     FALSE     TRUE
    219  * HQVInitPatch        TRUE       FALSE      FALSE     FALSE     FALSE
    220  * HQVDisablePatch     FALSE      TRUE       TRUE      TRUE      FALSE
    221  *
    222  * This is now up to date with CLEXF40040. All unused entries were removed.
    223  * The functions depending on this struct are untouched.
    224  */
    225 void
    226 VIAVidHWDiffInit(ScrnInfoPtr pScrn)
    227 {
    228     VIAPtr pVia = VIAPTR(pScrn);
    229     VIAHWDiff *HWDiff = &pVia->HWDiff;
    230 
    231     switch (pVia->Chipset) {
    232         case VIA_CLE266:
    233             if (CLE266_REV_IS_AX(pVia->ChipRev)) {
    234                 HWDiff->dwThreeHQVBuffer = VID_HWDIFF_FALSE;
    235                 HWDiff->dwHQVFetchByteUnit = VID_HWDIFF_FALSE;
    236                 HWDiff->dwSupportTwoColorKey = VID_HWDIFF_FALSE;
    237                 HWDiff->dwHQVInitPatch = VID_HWDIFF_TRUE;
    238                 HWDiff->dwHQVDisablePatch = VID_HWDIFF_FALSE;
    239                 HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE;
    240             } else {
    241                 HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE;
    242                 HWDiff->dwHQVFetchByteUnit = VID_HWDIFF_TRUE;
    243                 HWDiff->dwSupportTwoColorKey = VID_HWDIFF_TRUE;
    244                 HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE;
    245                 HWDiff->dwHQVDisablePatch = VID_HWDIFF_TRUE;
    246                 HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE;
    247             }
    248             HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE;
    249             break;
    250         case VIA_KM400:
    251             HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE;
    252             HWDiff->dwHQVFetchByteUnit = VID_HWDIFF_TRUE;
    253             HWDiff->dwSupportTwoColorKey = VID_HWDIFF_FALSE;
    254             HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE;
    255             HWDiff->dwHQVDisablePatch = VID_HWDIFF_TRUE;
    256             HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE;
    257             HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE;
    258             break;
    259         case VIA_K8M800:
    260             HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE;
    261             HWDiff->dwHQVFetchByteUnit = VID_HWDIFF_TRUE;
    262             HWDiff->dwSupportTwoColorKey = VID_HWDIFF_FALSE;
    263             HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE;
    264             HWDiff->dwHQVDisablePatch = VID_HWDIFF_TRUE;
    265             HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE;
    266             HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE;
    267             break;
    268         case VIA_PM800:
    269             HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE;
    270             HWDiff->dwHQVFetchByteUnit = VID_HWDIFF_TRUE;
    271             HWDiff->dwSupportTwoColorKey = VID_HWDIFF_TRUE;
    272             HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE;
    273             HWDiff->dwHQVDisablePatch = VID_HWDIFF_FALSE;
    274             HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE;
    275             HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE;
    276             HWDiff->HQVCmeRegs = hqv_cme_regs;
    277             break;
    278         case VIA_P4M800PRO:
    279         case VIA_P4M900:
    280             HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE;
    281             HWDiff->dwHQVFetchByteUnit = VID_HWDIFF_TRUE;
    282             HWDiff->dwSupportTwoColorKey = VID_HWDIFF_FALSE;
    283             HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE;
    284             HWDiff->dwHQVDisablePatch = VID_HWDIFF_TRUE;
    285             HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE;
    286             HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE;
    287             HWDiff->HQVCmeRegs = hqv_cme_regs;
    288             break;
    289         case VIA_K8M890:
    290             HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE;
    291             HWDiff->dwHQVFetchByteUnit = VID_HWDIFF_TRUE;
    292             HWDiff->dwSupportTwoColorKey = VID_HWDIFF_FALSE;
    293             HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE;
    294             HWDiff->dwHQVDisablePatch = VID_HWDIFF_TRUE;
    295             HWDiff->dwNeedV1Prefetch = VID_HWDIFF_TRUE;
    296             HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE;
    297             HWDiff->HQVCmeRegs = hqv_cme_regs;
    298             break;
    299         case VIA_P4M890:
    300             HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE;
    301             HWDiff->dwHQVFetchByteUnit = VID_HWDIFF_TRUE;
    302             HWDiff->dwSupportTwoColorKey = VID_HWDIFF_FALSE;
    303             HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE;
    304             HWDiff->dwHQVDisablePatch = VID_HWDIFF_TRUE;
    305             HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE;
    306             HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE;
    307             HWDiff->HQVCmeRegs = hqv_cme_regs;
    308             break;
    309         case VIA_CX700:
    310             HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE;
    311             HWDiff->dwHQVFetchByteUnit = VID_HWDIFF_TRUE;
    312             HWDiff->dwSupportTwoColorKey = VID_HWDIFF_TRUE;
    313             HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE;
    314             HWDiff->dwHQVDisablePatch = VID_HWDIFF_FALSE;
    315             HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE;
    316             HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE;
    317             HWDiff->HQVCmeRegs = hqv_cme_regs;
    318             break;
    319         case VIA_VX800:
    320             HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE;
    321             HWDiff->dwHQVFetchByteUnit = VID_HWDIFF_TRUE;
    322             HWDiff->dwSupportTwoColorKey = VID_HWDIFF_TRUE;
    323             HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE;
    324             HWDiff->dwHQVDisablePatch = VID_HWDIFF_FALSE;
    325             HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE;
    326             HWDiff->dwNewScaleCtl = VID_HWDIFF_TRUE;
    327             HWDiff->HQVCmeRegs = hqv_cme_regs;
    328             break;
    329         case VIA_VX855:
    330         case VIA_VX900:
    331             HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE;
    332             HWDiff->dwHQVFetchByteUnit = VID_HWDIFF_TRUE;
    333             HWDiff->dwSupportTwoColorKey = VID_HWDIFF_TRUE;
    334             HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE;
    335             HWDiff->dwHQVDisablePatch = VID_HWDIFF_FALSE;
    336             HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE;
    337             HWDiff->dwNewScaleCtl = VID_HWDIFF_TRUE;
    338             HWDiff->HQVCmeRegs = hqv_cme_regs_409;
    339             break;
    340         default:
    341             xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
    342                        "VIAVidHWDiffInit: Unhandled ChipSet.\n");
    343     }
    344 }
    345 
    346 /*
    347  * Old via_overlay code.
    348  */
    349 typedef struct _YCBCRREC
    350 {
    351     CARD32 dwY;
    352     CARD32 dwCB;
    353     CARD32 dwCR;
    354 } YCBCRREC;
    355 
    356 /*
    357  * Verify that using V1 bit definitions on V3
    358  * is not broken in OverlayGetV1V3Format().
    359  */
    360 
    361 #if V1_COLORSPACE_SIGN != V3_COLORSPACE_SIGN
    362 #error "V1_COLORSPACE_SIGN != V3_COLORSPACE_SIGN"
    363 #endif
    364 #if V1_YUV422 != V3_YUV422
    365 #error "V1_YUV422 != V3_YUV422"
    366 #endif
    367 #if V1_SWAP_HW_HQV != V3_SWAP_HW_HQV
    368 #error "V1_SWAP_HW_HQV != V3_SWAP_HW_HQV"
    369 #endif
    370 #if V1_RGB15 != V3_RGB15
    371 #error "V1_RGB15 != V3_RGB15"
    372 #endif
    373 #if V1_RGB16 != V3_RGB16
    374 #error "V1_RGB16 != V3_RGB16"
    375 #endif
    376 #if V1_RGB32 != V3_RGB32
    377 #error "V1_RGB32 != V3_RGB32"
    378 #endif
    379 
    380 static BOOL
    381 viaOverlayGetV1V3Format(VIAPtr pVia, int vport, /* 1 or 3, as in V1 or V3 */
    382                         unsigned long videoFlag, unsigned long *pVidCtl,
    383                         unsigned long *pHQVCtl)
    384 {
    385     if (videoFlag & VIDEO_HQV_INUSE) {
    386         switch (pVia->swov.SrcFourCC) {
    387             case FOURCC_YV12:
    388             case FOURCC_I420:
    389             case FOURCC_XVMC:
    390                 *pHQVCtl |= HQV_YUV420;
    391                 break;
    392             case FOURCC_YUY2:
    393                 *pHQVCtl |= HQV_YUV422;
    394                 break;
    395             case FOURCC_RV32:
    396                 *pVidCtl |= V1_RGB32;
    397                 *pHQVCtl |= HQV_RGB32;
    398                 break;
    399             case FOURCC_RV15:
    400                 *pVidCtl |= V1_RGB15;
    401                 *pHQVCtl |= HQV_RGB15;
    402                 break;
    403             case FOURCC_RV16:
    404                 *pVidCtl |= V1_RGB16;
    405                 *pHQVCtl |= HQV_RGB16;
    406                 break;
    407             default:
    408                 DBG_DD(ErrorF("viaOverlayGetV1V3Format: "
    409                               "Invalid FOURCC format (0x%lx).\n",
    410                               pVia->swov.SrcFourCC));
    411                 return FALSE;
    412         }
    413         *pVidCtl |= V1_SWAP_HW_HQV;
    414         *pHQVCtl |= HQV_SRC_SW | HQV_ENABLE | HQV_SW_FLIP;
    415     } else {
    416         switch (pVia->swov.SrcFourCC) {
    417             case FOURCC_YV12:
    418             case FOURCC_I420:
    419             case FOURCC_XVMC:
    420                 if (vport == 1) {
    421                     *pVidCtl |= V1_YCbCr420;
    422                 } else {
    423                     DBG_DD(ErrorF("viaOverlayGetV1V3Format: "
    424                                   "V3 does not support planar YUV.\n"));
    425                     return FALSE;
    426                 }
    427                 break;
    428             case FOURCC_YUY2:
    429                 *pVidCtl |= V1_YUV422;
    430                 break;
    431             case FOURCC_RV32:
    432             case FOURCC_RV15:
    433             case FOURCC_RV16:
    434                 ErrorF("viaOverlayGetV1V3Format: "
    435                        "Can't display RGB video in this configuration.\n");
    436                 return FALSE;
    437             default:
    438                 DBG_DD(ErrorF("viaOverlayGetV1V3Format: "
    439                               "Invalid FOURCC format (0x%lx).\n",
    440                               pVia->swov.SrcFourCC));
    441                 return FALSE;
    442         }
    443     }
    444     *pVidCtl |= V1_COLORSPACE_SIGN;
    445     return TRUE;
    446 }
    447 
    448 static unsigned long
    449 viaOverlayGetSrcStartAddress(VIAPtr pVia,
    450                              unsigned long videoFlag,
    451                              LPDDUPDATEOVERLAY pUpdate,
    452                              unsigned long srcPitch,
    453                              unsigned long *pHQVoffset)
    454 {
    455     unsigned long srcWidth =
    456             (unsigned long)(pUpdate->SrcRight - pUpdate->SrcLeft);
    457     unsigned long dstWidth =
    458             (unsigned long)(pUpdate->DstRight - pUpdate->DstLeft);
    459     unsigned long srcHeight =
    460             (unsigned long)(pUpdate->SrcBottom - pUpdate->SrcTop);
    461     unsigned long dstHeight =
    462             (unsigned long)(pUpdate->DstBottom - pUpdate->DstTop);
    463 
    464     unsigned long offset = 0;
    465     unsigned long srcTopOffset = 0;
    466     unsigned long srcLeftOffset = 0;
    467 
    468     int n = 1;
    469 
    470     if ((pUpdate->SrcLeft != 0) || (pUpdate->SrcTop != 0)) {
    471         switch (pVia->swov.SrcFourCC) {
    472             case FOURCC_RV32:
    473                 n = 2;
    474             case FOURCC_YUY2:
    475             case FOURCC_UYVY:
    476             case FOURCC_RV15:
    477             case FOURCC_RV16:
    478 
    479                 if (videoFlag & VIDEO_HQV_INUSE) {
    480                     offset = (((pUpdate->SrcTop & ~3) * srcPitch)
    481                               + ((pUpdate->SrcLeft << n) & ~31));
    482 
    483                     if (srcHeight > dstHeight)
    484                         srcTopOffset = ((pUpdate->SrcTop & ~3)
    485                                         * dstHeight / srcHeight) * srcPitch;
    486                     else
    487                         srcTopOffset = (pUpdate->SrcTop & ~3) * srcPitch;
    488 
    489                     if (srcWidth > dstWidth)
    490                         srcLeftOffset = (((pUpdate->SrcLeft << n) & ~31)
    491                                          * dstWidth / srcWidth);
    492                     else
    493                         srcLeftOffset = (pUpdate->SrcLeft << n) & ~31;
    494                     *pHQVoffset = srcTopOffset + srcLeftOffset;
    495                 } else
    496                     offset = ((pUpdate->SrcTop * srcPitch)
    497                               + ((pUpdate->SrcLeft << n) & ~15));
    498                 break;
    499 
    500             case FOURCC_YV12:
    501             case FOURCC_I420:
    502             case FOURCC_XVMC:
    503 
    504                 if (videoFlag & VIDEO_HQV_INUSE)
    505                     offset = (((pUpdate->SrcTop & ~3) * (srcPitch << 1))
    506                               + ((pUpdate->SrcLeft << 1) & ~31));
    507                 else {
    508                     offset = ((((pUpdate->SrcTop & ~3) * srcPitch)
    509                                + pUpdate->SrcLeft) & ~31);
    510                     if (pUpdate->SrcTop > 0)
    511                         pVia->swov.overlayRecordV1.dwUVoffset
    512                                 = (((((pUpdate->SrcTop & ~3) >> 1) * srcPitch)
    513                                     + pUpdate->SrcLeft) & ~31) >> 1;
    514                     else
    515                         pVia->swov.overlayRecordV1.dwUVoffset = offset >> 1;
    516                 }
    517                 break;
    518 
    519             default:
    520                 DBG_DD(ErrorF("viaGetSrcStartAddress: "
    521                               "Invalid FOURCC format (0x%lx).\n",
    522                               pVia->swov.SrcFourCC));
    523                 break;
    524         }
    525     } else {
    526         pVia->swov.overlayRecordV1.dwUVoffset = offset = 0;
    527     }
    528 
    529     return offset;
    530 }
    531 
    532 static YCBCRREC
    533 viaOverlayGetYCbCrStartAddress(unsigned long videoFlag,
    534                                unsigned long startAddr, unsigned long offset,
    535                                unsigned long UVoffset, unsigned long srcPitch,
    536                                unsigned long srcHeight)
    537 {
    538     YCBCRREC YCbCr;
    539 
    540     if (videoFlag & VIDEO_HQV_INUSE) {
    541         YCbCr.dwY = startAddr;
    542         YCbCr.dwCB = startAddr + srcPitch * srcHeight;
    543         YCbCr.dwCR = (startAddr + srcPitch * srcHeight
    544                       + srcPitch * (srcHeight >> 2));
    545     } else {
    546         YCbCr.dwY = startAddr + offset;
    547         YCbCr.dwCB = startAddr + srcPitch * srcHeight + UVoffset;
    548         YCbCr.dwCR = (startAddr + srcPitch * srcHeight + UVoffset
    549                       + srcPitch * (srcHeight >> 2));
    550     }
    551     return YCbCr;
    552 }
    553 
    554 static unsigned long
    555 viaOverlayHQVCalcZoomWidth(VIAPtr pVia,
    556                            unsigned long videoFlag, unsigned long srcWidth,
    557                            unsigned long dstWidth, unsigned long *pZoomCtl,
    558                            unsigned long *pMiniCtl,
    559                            unsigned long *pHQVfilterCtl,
    560                            unsigned long *pHQVminiCtl,
    561                            unsigned long *pHQVscaleCtlH,
    562                            unsigned long *pHQVzoomflag)
    563 {
    564     unsigned long tmp, sw1, d, falign, mdiv;
    565     Bool zoom_ok = TRUE;
    566     VIAHWDiff *hwDiff = &pVia->HWDiff;
    567 
    568     CARD32 HQVfilter[5] = { HQV_H_FILTER_DEFAULT, HQV_H_TAP4_121,
    569         HQV_H_TAP4_121, HQV_H_TAP8_12221, HQV_H_TAP8_12221
    570     };
    571     /* CARD HQVmini[5] = { 0, 0xc00, 0xa00, 0x900, 0x8800 }; */
    572 
    573     falign = 0;
    574     mdiv = 1;
    575 
    576     if (srcWidth == dstWidth) { /* No zoom */
    577         *pHQVfilterCtl |= HQV_H_FILTER_DEFAULT;
    578     } else if (srcWidth < dstWidth) { /* Zoom in */
    579 			*pZoomCtl &= 0x0000FFFF;
    580 	        tmp = srcWidth * 0x800 / dstWidth;
    581 	        *pZoomCtl |= ((tmp & 0x7ff) << 16) | V1_X_ZOOM_ENABLE;
    582 	        *pMiniCtl |= V1_X_INTERPOLY;
    583 	        zoom_ok = !(tmp > 0x7ff);
    584 
    585 	        *pHQVzoomflag = 1;
    586 	        *pHQVfilterCtl |= HQV_H_FILTER_DEFAULT;
    587     } else { /* srcWidth > dstWidth - Zoom out */
    588 		if (hwDiff->dwNewScaleCtl) {
    589             if (srcWidth > (dstWidth << 3)) {
    590                 /*<1/8*/
    591                 /*FIXME!*/
    592                 if (dstWidth <= 32) {
    593                     dstWidth = 33;
    594                 }
    595                 if (srcWidth > (dstWidth << 5)) {
    596                     tmp = 1 * 0x1000 / 31;
    597                 } else {
    598                     tmp = (dstWidth * 0x1000) / srcWidth;
    599                 }
    600 
    601                 *pHQVscaleCtlH = HQV_H_SCALE_DOWN_UNDER_EIGHTH;
    602             } else if (srcWidth == (dstWidth << 3)) {
    603                 /*1/8*/
    604                 tmp = ((dstWidth - 1) * 0x1000) / srcWidth;
    605                 *pHQVscaleCtlH = HQV_H_SCALE_DOWN_UNDER_EIGHTH;
    606             } else if (srcWidth > (dstWidth << 2)) {
    607                 /*1/4 -1/8 zoom-out*/
    608                 tmp = (srcWidth * 0x1000) / dstWidth;
    609                 *pHQVscaleCtlH = HQV_H_SCALE_DOWN_FOURTH_TO_EIGHTH;
    610             } else {
    611                 /*1-1/4 zoom-out*/
    612                 /*setting :src/(destination+0.5)*/
    613                 tmp = (srcWidth * 0x2000) / ((dstWidth << 1) + 1);
    614                 *pHQVscaleCtlH = HQV_H_SCALE_DOWN_FOURTH_TO_1;
    615             }
    616 
    617             /*rounding to nearest interger*/
    618             tmp += (((tmp * 0x1000) & 0xfff) > 1) ? 1 : 0;
    619             *pHQVscaleCtlH |= (tmp & 0x7fff) | HQV_H_SCALE_ENABLE;
    620 		} else {
    621 	        /* HQV rounding patch, instead of:
    622 	         * //tmp = dstWidth*0x0800 / srcWidth; */
    623 	        tmp = dstWidth * 0x800 * 0x400 / srcWidth;
    624 	        tmp = tmp / 0x400 + ((tmp & 0x3ff) ? 1 : 0);
    625 
    626 	        *pHQVminiCtl = (tmp & 0x7ff) | HQV_H_MINIFY_ENABLE | HQV_H_MINIFY_DOWN;
    627 
    628 	        *pHQVminiCtl |= HQV_HDEBLOCK_FILTER;
    629 		}
    630         /* Scale down the picture by a factor mdiv = (1 << d) = {2, 4, 8 or 16} */
    631 
    632         sw1 = srcWidth;
    633         for (d = 1; d < 5; d++) {
    634             sw1 >>= 1;
    635             if (sw1 <= dstWidth)
    636                 break;
    637         }
    638         if (d == 5) { /* Too small. */
    639             d = 4;
    640             zoom_ok = FALSE;
    641         }
    642         mdiv = 1 << d; /* <= {2,4,8,16} */
    643         falign = ((mdiv << 1) - 1) & 0xf; /* <= {3,7,15,15} */
    644         *pMiniCtl |= V1_X_INTERPOLY;
    645         *pMiniCtl |= ((d << 1) - 1) << 24; /* <= {1,3,5,7} << 24 */
    646 
    647         *pHQVfilterCtl |= HQVfilter[d];
    648 
    649 	/* Scale to arbitrary size, on top of previous scaling by (1 << d). */
    650 
    651 	if (sw1 < dstWidth) {
    652 		/* CLE bug
    653 		*pZoomCtl = sw1 * 0x0800 / dstWidth;*/
    654 		*pZoomCtl = (sw1 - 2) * 0x0800 / dstWidth;
    655 		*pZoomCtl = ((*pZoomCtl & 0x7ff) << 16) | V1_X_ZOOM_ENABLE;
    656 	}
    657 
    658 	if (videoFlag & VIDEO_1_INUSE) {
    659 		pVia->swov.overlayRecordV1.dwFetchAlignment = falign;
    660 		pVia->swov.overlayRecordV1.dwminifyH = mdiv;
    661 	} else {
    662 		pVia->swov.overlayRecordV3.dwFetchAlignment = falign;
    663 		pVia->swov.overlayRecordV3.dwminifyH = mdiv;
    664 	}
    665     }
    666     return zoom_ok;
    667 }
    668 
    669 static unsigned long
    670 viaOverlayHQVCalcZoomHeight(VIAPtr pVia,
    671                             unsigned long srcHeight, unsigned long dstHeight,
    672                             unsigned long *pZoomCtl, unsigned long *pMiniCtl,
    673                             unsigned long *pHQVfilterCtl,
    674                             unsigned long *pHQVminiCtl,
    675                             unsigned long *pHQVscaleCtlV,
    676                             unsigned long *pHQVzoomflag)
    677 {
    678     unsigned long tmp, sh1, d;
    679     Bool zoom_ok = TRUE;
    680     VIAHWDiff *hwDiff = &pVia->HWDiff;
    681 
    682     CARD32 HQVfilter[5] = { HQV_V_TAP4_121, HQV_V_TAP4_121, HQV_V_TAP4_121,
    683                             HQV_V_TAP8_12221, HQV_V_TAP8_12221 };
    684     /* CARD32 HQVmini[5] = { 0, 0x0c000000, 0x0a000000, 0x09000000, 0x08800000 }; */
    685 
    686     /*if (pVia->pBIOSInfo->scaleY)
    687      * {
    688      * dstHeight = dstHeight + 1;
    689      * } */
    690 
    691     if (srcHeight == dstHeight) { /* No zoom */
    692         *pHQVfilterCtl |= HQV_V_TAP4_121;
    693     } else if (srcHeight < dstHeight) { /* Zoom in */
    694 		*pZoomCtl &= 0xFFFF0000;
    695 	    tmp = srcHeight * 0x400 / dstHeight - 1;
    696 	    *pZoomCtl |= ((tmp & 0x3ff) | V1_Y_ZOOM_ENABLE);
    697 	    *pMiniCtl |= (V1_Y_INTERPOLY | V1_YCBCR_INTERPOLY);
    698 
    699 	    *pHQVzoomflag = 1;
    700 	    *pHQVfilterCtl |= HQV_V_TAP4_121;
    701     } else { /* srcHeight > dstHeight - Zoom out */
    702 	if (hwDiff->dwNewScaleCtl) {
    703             /*setting :src/(destination+0.5)*/
    704             tmp = srcHeight * 0x2000 / ((dstHeight << 1) + 1);
    705             tmp += (((tmp * 0x1000) & 0xfff) > 1) ? 1 : 0;
    706             if ((tmp & 0x1ffff) == 0) {
    707                 tmp = 0x1ffff;
    708             }
    709 
    710             *pHQVscaleCtlV = (tmp & 0x1ffff) | HQV_V_SCALE_ENABLE| HQV_V_SCALE_DOWN;
    711 	} else {
    712 	        /* HQV rounding patch, instead of:
    713 	         * //tmp = dstHeight*0x0800 / srcHeight; */
    714 	        tmp = dstHeight * 0x0800 * 0x400 / srcHeight;
    715 	        tmp = tmp / 0x400 + ((tmp & 0x3ff) ? 1 : 0);
    716 	        *pHQVminiCtl |= (((tmp & 0x7ff) << 16) | HQV_V_MINIFY_ENABLE
    717 	                         | HQV_V_MINIFY_DOWN);
    718 
    719 	        /* Scale down the picture by a factor (1 << d) = {2, 4, 8 or 16} */
    720 	        sh1 = srcHeight;
    721 	        for (d = 1; d < 5; d++) {
    722 	            sh1 >>= 1;
    723 	            if (sh1 <= dstHeight)
    724 	                break;
    725 	        }
    726 	        if (d == 5) { /* Too small. */
    727 	            d = 4;
    728 	            zoom_ok = FALSE;
    729 	        }
    730 
    731 	        *pMiniCtl |= ((d << 1) - 1) << 16; /* <= {1,3,5,7} << 16 */
    732 
    733 	        *pHQVfilterCtl |= HQVfilter[d];
    734 	        /* *pHQVminiCtl |= HQVmini[d]; */
    735 	        *pHQVminiCtl |= HQV_VDEBLOCK_FILTER;
    736 
    737 	        /* Scale to arbitrary size, on top of previous scaling by (1 << d). */
    738 
    739 	        if (sh1 < dstHeight) {
    740 	            tmp = sh1 * 0x0400 / dstHeight;
    741 	            *pZoomCtl |= ((tmp & 0x3ff) | V1_Y_ZOOM_ENABLE);
    742 	            *pMiniCtl |= V1_Y_INTERPOLY | V1_YCBCR_INTERPOLY;
    743 	        }
    744 	}
    745     }
    746     return zoom_ok;
    747 }
    748 
    749 static unsigned long
    750 viaOverlayGetFetch(VIAPtr pVia, unsigned long videoFlag,
    751                    unsigned long srcWidth, unsigned long dstWidth,
    752                    unsigned long oriSrcWidth, unsigned long *pHQVsrcFetch)
    753 {
    754     unsigned long fetch = 0;
    755     int n = 2; /* 2^n bytes per pixel. */
    756 
    757     switch (pVia->swov.SrcFourCC) {
    758         case FOURCC_YV12:
    759         case FOURCC_I420:
    760         case FOURCC_XVMC:
    761             n = 0; /* 2^n = 1 byte per pixel (Y channel in planar YUV) */
    762             break;
    763         case FOURCC_UYVY:
    764         case FOURCC_YUY2:
    765         case FOURCC_RV15:
    766         case FOURCC_RV16:
    767             n = 1; /* 2^n = 2 bytes per pixel (packed YUV) */
    768             break;
    769         case FOURCC_RV32:
    770             n = 2;
    771             break;
    772         default:
    773             DBG_DD(ErrorF("viaOverlayGetFetch: "
    774                           "Invalid FOURCC format (0x%lx).\n",
    775                           pVia->swov.SrcFourCC));
    776             break;
    777     }
    778 
    779     if (videoFlag & VIDEO_HQV_INUSE) {
    780         *pHQVsrcFetch = oriSrcWidth << n;
    781         if (n == 0) {
    782             /* Assume n == 0 <=> Planar YUV.
    783              * The V1/V3 pixelformat is always packed YUV when we use HQV,
    784              * so we switch from 8-bit to 16-bit pixels here.
    785              */
    786             n = 1;
    787         }
    788         if (dstWidth >= srcWidth)
    789             fetch = (ALIGN_TO(srcWidth << n, 16) >> 4) + 1;
    790         else
    791             fetch = (ALIGN_TO(dstWidth << n, 16) >> 4) + 1;
    792     } else {
    793         if (n == 0)
    794             fetch = (ALIGN_TO(srcWidth, 32) >> 4);
    795         else
    796             fetch = (ALIGN_TO(srcWidth << n, 16) >> 4) + 1;
    797     }
    798 
    799     /* Fix planar mode problem. */
    800     if (fetch < 4)
    801         fetch = 4;
    802 
    803     return fetch;
    804 }
    805 
    806 /*
    807  * This function uses quadratic mapping to adjust the midpoint of the scaling.
    808  */
    809 static float
    810 rangeEqualize(float inLow, float inHigh, float outLow, float outHigh,
    811               float outMid, float inValue)
    812 {
    813     float inRange = inHigh - inLow,
    814           outRange = outHigh - outLow,
    815           normIn = ((inValue - inLow) / inRange) * 2. - 1.,
    816           delta = outMid - outRange * 0.5 - outLow;
    817     return ((inValue - inLow) * outRange / inRange + outLow
    818             + (1. - normIn * normIn) * delta);
    819 }
    820 
    821 static unsigned
    822 vPackFloat(float val, float hiLimit, float loLimit, float mult, int shift,
    823            Bool doSign)
    824 {
    825     unsigned packed, mask, sign;
    826 
    827     val = (val > hiLimit) ? hiLimit : val;
    828     val = (val < loLimit) ? loLimit : val;
    829     sign = (val < 0) ? 1 : 0;
    830     val = (sign) ? -val : val;
    831     packed = ((unsigned)(val * mult + 1.)) >> 1;
    832     mask = (1 << shift) - 1;
    833     return (((packed >= mask) ? mask : packed)
    834             | ((doSign) ? (sign << shift) : 0));
    835 
    836 }
    837 
    838 typedef float colorCoeff[5];
    839 static colorCoeff colorCTable[] = {
    840     {1.1875, 1.625, 0.875, 0.375, 2.0},
    841     {1.164, 1.596, 0.54, 0.45, 2.2}
    842 };
    843 
    844 /*
    845  * This function is a partial rewrite of the overlay.c file of the original VIA
    846  * drivers, which was extremely nasty and difficult to follow. Coefficients for
    847  * new chipset models should be added in the table above and, if needed,
    848  * implemented in the model switch below.
    849  */
    850 static void
    851 viaCalculateVideoColor(VIAPtr pVia, int hue, int saturation,
    852                        int brightness, int contrast, Bool reset,
    853                        CARD32 * col1, CARD32 * col2)
    854 {
    855     float fA, fB1, fC1, fD, fB2, fC2, fB3, fC3;
    856     float fPI, fContrast, fSaturation, fHue, fBrightness;
    857     const float *mCoeff;
    858     unsigned long dwA, dwB1, dwC1, dwD, dwB2, dwC2, dwB3, dwC3, dwS;
    859     unsigned long dwD_Int, dwD_Dec;
    860     int intD;
    861     int model;
    862 
    863     fPI = (float)(M_PI / 180.);
    864 
    865     if (reset) {
    866         saturation = 10000;
    867         brightness = 5000;
    868         contrast = 10000;
    869     }
    870 
    871     switch (pVia->ChipId) {
    872         case PCI_CHIP_VT3205:
    873         case PCI_CHIP_VT3204:
    874         case PCI_CHIP_VT3259:
    875         case PCI_CHIP_VT3314:
    876         case PCI_CHIP_VT3336:
    877         case PCI_CHIP_VT3364:
    878         case PCI_CHIP_VT3324:
    879         case PCI_CHIP_VT3327:
    880         case PCI_CHIP_VT3353:
    881         case PCI_CHIP_VT3409:
    882         case PCI_CHIP_VT3410:
    883             model = 0;
    884             break;
    885         case PCI_CHIP_CLE3122:
    886             model = (CLE266_REV_IS_CX(pVia->ChipRev) ? 0 : 1);
    887             break;
    888         default:
    889             ErrorF("Unknown Chip ID\n");
    890             model = 0;
    891     }
    892 
    893     switch (model) {
    894         case 0:
    895             fBrightness = rangeEqualize(0., 10000., -128., 128., -16.,
    896                                         (float)brightness);
    897             fContrast = rangeEqualize(0., 20000., 0., 1.6645, 1.0,
    898                                       (float)contrast);
    899             fSaturation = rangeEqualize(0., 20000, 0., 2., 1.,
    900                                         (float)saturation);
    901             break;
    902         default:
    903             fBrightness = rangeEqualize(0., 10000., -128., 128., -12.,
    904                                         (float)brightness);
    905             fContrast = rangeEqualize(0., 20000., 0., 1.6645, 1.1,
    906                                       (float)contrast);
    907             fSaturation = rangeEqualize(0., 20000, 0., 2., 1.15,
    908                                         (float)saturation);
    909             break;
    910     }
    911     fHue = (float)hue;
    912 
    913     mCoeff = colorCTable[model];
    914 
    915     fA = (float)(mCoeff[0] * fContrast);
    916     fB1 = (float)(-mCoeff[1] * fContrast * fSaturation * sin(fHue * fPI));
    917     fC1 = (float)(mCoeff[1] * fContrast * fSaturation * cos(fHue * fPI));
    918     fD = (float)(mCoeff[0] * (fBrightness));
    919     fB2 = (float)((mCoeff[2] * sin(fHue * fPI) - mCoeff[3] * cos(fHue * fPI))
    920                   * fContrast * fSaturation);
    921     fC2 = (float)(-(mCoeff[2] * cos(fHue * fPI) + mCoeff[3] * sin(fHue * fPI))
    922                   * fContrast * fSaturation);
    923     fB3 = (float)(mCoeff[4] * fContrast * fSaturation * cos(fHue * fPI));
    924     fC3 = (float)(mCoeff[4] * fContrast * fSaturation * sin(fHue * fPI));
    925 
    926     switch (model) {
    927         case 0:
    928             dwA = vPackFloat(fA, 1.9375, 0., 32., 5, 0);
    929             dwB1 = vPackFloat(fB1, 2.125, -2.125, 16., 5, 1);
    930             dwC1 = vPackFloat(fC1, 2.125, -2.125, 16., 5, 1);
    931 
    932             if (fD >= 0) {
    933                 intD = (int)fD;
    934                 if (intD > 127)
    935                     intD = 127;
    936                 dwD_Int = ((unsigned long)intD) & 0xff;
    937                 dwD = ((unsigned long)(fD * 16 + 1)) >> 1;
    938                 dwD_Dec = dwD & 0x7;
    939             } else {
    940                 intD = (int)fD;
    941                 if (intD < -128)
    942                     intD = -128;
    943                 intD = intD + 256;
    944                 dwD_Int = ((unsigned long)intD) & 0xff;
    945                 fD = -fD;
    946                 dwD = ((unsigned long)(fD * 16 + 1)) >> 1;
    947                 dwD_Dec = dwD & 0x7;
    948             }
    949 
    950             dwB2 = vPackFloat(fB2, 1.875, -1.875, 16, 4, 1);
    951             dwC2 = vPackFloat(fC2, 1.875, -1.875, 16, 4, 1);
    952             dwB3 = vPackFloat(fB3, 3.875, -3.875, 16, 5, 1);
    953             dwC3 = vPackFloat(fC3, 3.875, -3.875, 16, 5, 1);
    954             *col1 = (dwA << 24) | (dwB1 << 16) | (dwC1 << 8) | dwD_Int;
    955             *col2 = (dwD_Dec << 29 | dwB2 << 24) | (dwC2 << 16) | (dwB3 << 8)
    956                     | (dwC3);
    957             break;
    958 
    959         default:
    960             dwA = vPackFloat(fA, 1.9375, -0., 32, 5, 0);
    961             dwB1 = vPackFloat(fB1, 0.75, -0.75, 8., 2, 1);
    962             dwC1 = vPackFloat(fC1, 2.875, 1., 16., 5, 0);
    963 
    964             if (fD >= 127)
    965                 fD = 127;
    966 
    967             if (fD <= -128)
    968                 fD = -128;
    969 
    970             if (fD >= 0) {
    971                 dwS = 0;
    972             } else {
    973                 dwS = 1;
    974                 fD = fD + 128;
    975             }
    976 
    977             dwD = ((unsigned long)(fD * 2 + 1)) >> 1;
    978             if (dwD >= 0x7f) {
    979                 dwD = 0x7f | (dwS << 7);
    980             } else {
    981                 dwD = (dwD & 0x7f) | (dwS << 7);
    982             }
    983 
    984             dwB2 = vPackFloat(fB2, 0., -0.875, 16., 3, 0);
    985             dwC2 = vPackFloat(fC2, 0., -1.875, 16., 4, 0);
    986             dwB3 = vPackFloat(fB3, 3.75, 0., 8., 4, 0);
    987             dwC3 = vPackFloat(fC3, 1.25, -1.25, 8., 3, 1);
    988             *col1 = (dwA << 24) | (dwB1 << 18) | (dwC1 << 9) | dwD;
    989             *col2 = (dwB2 << 25) | (dwC2 << 17) | (dwB3 << 10) | (dwC3 << 2);
    990             break;
    991     }
    992 }
    993 
    994 /*
    995  *
    996  *
    997  */
    998 void
    999 viaSetColorSpace(VIAPtr pVia, int hue, int saturation, int brightness,
   1000                  int contrast, Bool reset)
   1001 {
   1002     CARD32 col1, col2;
   1003 
   1004     viaCalculateVideoColor(pVia, hue, saturation, brightness, contrast, reset,
   1005                            &col1, &col2);
   1006     switch (pVia->ChipId) {
   1007         case PCI_CHIP_VT3205:
   1008         case PCI_CHIP_VT3204:
   1009         case PCI_CHIP_VT3314:
   1010             VIASETREG(V3_ColorSpaceReg_1, col1);
   1011             VIASETREG(V3_ColorSpaceReg_2, col2);
   1012             DBG_DD(ErrorF("000002C4 %08lx\n", col1));
   1013             DBG_DD(ErrorF("000002C8 %08lx\n", col2));
   1014         case PCI_CHIP_VT3259:
   1015         case PCI_CHIP_VT3327:
   1016         case PCI_CHIP_VT3336:
   1017         case PCI_CHIP_VT3324:
   1018         case PCI_CHIP_VT3364:
   1019         case PCI_CHIP_VT3353:
   1020         case PCI_CHIP_VT3409:
   1021         case PCI_CHIP_VT3410:
   1022         case PCI_CHIP_CLE3122:
   1023             VIASETREG(V1_ColorSpaceReg_1, col1);
   1024             VIASETREG(V1_ColorSpaceReg_2, col2);
   1025             DBG_DD(ErrorF("00000288 %08lx\n", col2));
   1026             DBG_DD(ErrorF("00000284 %08lx\n", col1));
   1027             break;
   1028         default:
   1029             DBG_DD(ErrorF("Unknown DeviceID\n"));
   1030             break;
   1031     }
   1032 }
   1033 
   1034 static unsigned long
   1035 ViaInitVideoStatusFlag(VIAPtr pVia)
   1036 {
   1037     switch (pVia->ChipId) {
   1038         case PCI_CHIP_VT3205:
   1039         case PCI_CHIP_VT3204:
   1040         case PCI_CHIP_VT3314:
   1041             return VIDEO_HQV_INUSE | SW_USE_HQV | VIDEO_3_INUSE;
   1042         case PCI_CHIP_VT3259:
   1043         case PCI_CHIP_VT3327:
   1044         case PCI_CHIP_VT3336:
   1045         case PCI_CHIP_VT3324:
   1046         case PCI_CHIP_VT3364:
   1047         case PCI_CHIP_VT3353:
   1048         case PCI_CHIP_VT3409:
   1049         case PCI_CHIP_VT3410:
   1050             return (VIDEO_HQV_INUSE | SW_USE_HQV | VIDEO_1_INUSE
   1051                     | VIDEO_ACTIVE | VIDEO_SHOW);
   1052         case PCI_CHIP_CLE3122:
   1053             return VIDEO_HQV_INUSE | SW_USE_HQV | VIDEO_1_INUSE;
   1054         default:
   1055             DBG_DD(ErrorF("Unknown DeviceID\n"));
   1056             break;
   1057     }
   1058     return 0;
   1059 }
   1060 
   1061 static unsigned long
   1062 ViaSetVidCtl(VIAPtr pVia, unsigned int videoFlag)
   1063 {
   1064     if (videoFlag & VIDEO_1_INUSE) {
   1065         /*=* Modify for C1 FIFO *=*/
   1066         /* WARNING: not checking Chipset! */
   1067         if (CLE266_REV_IS_CX(pVia->ChipRev))
   1068             return V1_ENABLE | V1_EXPIRE_NUM_F;
   1069         else {
   1070             /* Overlay source format for V1 */
   1071             if (pVia->swov.gdwUseExtendedFIFO)
   1072                 return V1_ENABLE | V1_EXPIRE_NUM_A | V1_FIFO_EXTENDED;
   1073             else
   1074                 return V1_ENABLE | V1_EXPIRE_NUM;
   1075         }
   1076     } else {
   1077         switch (pVia->ChipId) {
   1078             case PCI_CHIP_VT3205:
   1079             case PCI_CHIP_VT3204:
   1080             case PCI_CHIP_VT3259:
   1081             case PCI_CHIP_VT3314:
   1082                 return V3_ENABLE | V3_EXPIRE_NUM_3205;
   1083             case PCI_CHIP_VT3327:
   1084             case PCI_CHIP_VT3336:
   1085             case PCI_CHIP_VT3324:
   1086             case PCI_CHIP_VT3364:
   1087             case PCI_CHIP_VT3353:
   1088                 return V3_ENABLE | VIDEO_EXPIRE_NUM_VT3336;
   1089             case PCI_CHIP_VT3409:
   1090             case PCI_CHIP_VT3410:
   1091                 return V3_ENABLE | VIDEO_EXPIRE_NUM_VT3409;
   1092             case PCI_CHIP_CLE3122:
   1093                 if (CLE266_REV_IS_CX(pVia->ChipRev))
   1094                     return V3_ENABLE | V3_EXPIRE_NUM_F;
   1095                 else
   1096                     return V3_ENABLE | V3_EXPIRE_NUM;
   1097             default:
   1098                 DBG_DD(ErrorF("Unknown DeviceID\n"));
   1099                 break;
   1100         }
   1101     }
   1102     return 0;
   1103 }
   1104 
   1105 /*
   1106  * Fill the buffer with 0x8000 (YUV2 black).
   1107  */
   1108 static void
   1109 ViaYUVFillBlack(VIAPtr pVia, void *buf, int num)
   1110 {
   1111     CARD16 *ptr = (CARD16 *) buf;
   1112 
   1113     while (num-- > 0)
   1114 #if X_BYTE_ORDER == X_LITTLE_ENDIAN
   1115         *ptr++ = 0x0080;
   1116 #else
   1117         *ptr++ = 0x8000;
   1118 #endif
   1119 }
   1120 
   1121 /*
   1122  * Add an HQV surface to an existing FOURCC surface.
   1123  * numbuf: number of buffers, 1, 2 or 3
   1124  * fourcc: FOURCC code of the current (already existing) surface
   1125  */
   1126 static long
   1127 AddHQVSurface(ScrnInfoPtr pScrn, unsigned int numbuf, CARD32 fourcc)
   1128 {
   1129     unsigned int i, width, height, pitch, fbsize, addr;
   1130     BOOL isplanar;
   1131     void *buf;
   1132 
   1133     VIAPtr pVia = VIAPTR(pScrn);
   1134     CARD32 AddrReg[3] = { HQV_DST_STARTADDR0, HQV_DST_STARTADDR1,
   1135             HQV_DST_STARTADDR2 };
   1136     unsigned long proReg = 0;
   1137 
   1138     if (pVia->ChipId == PCI_CHIP_VT3259 &&
   1139         !(pVia->swov.gdwVideoFlagSW & VIDEO_1_INUSE))
   1140         proReg = PRO_HQV1_OFFSET;
   1141 
   1142     isplanar = ((fourcc == FOURCC_YV12) || (fourcc == FOURCC_I420) ||
   1143                 (fourcc == FOURCC_XVMC));
   1144 
   1145     width = pVia->swov.SWDevice.gdwSWSrcWidth;
   1146     height = pVia->swov.SWDevice.gdwSWSrcHeight;
   1147     pitch = pVia->swov.SWDevice.dwPitch;
   1148     fbsize = pitch * height * (isplanar ? 2 : 1);
   1149 
   1150     pVia->swov.HQVMem = drm_bo_alloc(pScrn, fbsize * numbuf, 1, TTM_PL_FLAG_VRAM);
   1151     if (!pVia->swov.HQVMem)
   1152         return BadAlloc;
   1153     addr = pVia->swov.HQVMem->offset;
   1154     buf = drm_bo_map(pScrn, pVia->swov.HQVMem);
   1155 
   1156     ViaYUVFillBlack(pVia, buf, fbsize);
   1157 
   1158     for (i = 0; i < numbuf; i++) {
   1159         pVia->swov.overlayRecordV1.dwHQVAddr[i] = addr;
   1160         VIASETREG(AddrReg[i] + proReg, addr);
   1161         addr += fbsize;
   1162     }
   1163     drm_bo_unmap(pScrn, pVia->swov.HQVMem);
   1164     return Success;
   1165 }
   1166 
   1167 /*
   1168  * Create a FOURCC surface.
   1169  * doalloc: set true to actually allocate memory for the framebuffers
   1170  */
   1171 static long
   1172 CreateSurface(ScrnInfoPtr pScrn, CARD32 FourCC, CARD16 Width,
   1173               CARD16 Height, BOOL doalloc)
   1174 {
   1175     VIAPtr pVia = VIAPTR(pScrn);
   1176     unsigned long pitch, fbsize, addr;
   1177     BOOL isplanar;
   1178     void *buf;
   1179 
   1180     pVia->swov.SrcFourCC = FourCC;
   1181     pVia->swov.gdwVideoFlagSW = ViaInitVideoStatusFlag(pVia);
   1182 
   1183     isplanar = FALSE;
   1184     switch (FourCC) {
   1185         case FOURCC_YV12:
   1186         case FOURCC_I420:
   1187         case FOURCC_XVMC:
   1188             isplanar = TRUE;
   1189             pitch = ALIGN_TO(Width, 32);
   1190             fbsize = pitch * Height * 1.5;
   1191             break;
   1192         case FOURCC_RV32:
   1193             pitch = ALIGN_TO(Width << 2, 32);
   1194             fbsize = pitch * Height;
   1195             break;
   1196         default:
   1197             pitch = ALIGN_TO(Width << 1, 32);
   1198             fbsize = pitch * Height;
   1199             break;
   1200     }
   1201 
   1202     if (doalloc) {
   1203         pVia->swov.SWfbMem = drm_bo_alloc(pScrn, fbsize * 2, 1, TTM_PL_FLAG_VRAM);
   1204         if (!pVia->swov.SWfbMem)
   1205             return BadAlloc;
   1206         addr = pVia->swov.SWfbMem->offset;
   1207         buf = drm_bo_map(pScrn, pVia->swov.SWfbMem);
   1208 
   1209         ViaYUVFillBlack(pVia, buf, fbsize);
   1210 
   1211         pVia->swov.SWDevice.dwSWPhysicalAddr[0] = addr;
   1212         pVia->swov.SWDevice.dwSWPhysicalAddr[1] = addr + fbsize;
   1213         pVia->swov.SWDevice.lpSWOverlaySurface[0] = buf;
   1214         pVia->swov.SWDevice.lpSWOverlaySurface[1] = buf + fbsize;
   1215 
   1216         if (isplanar) {
   1217             pVia->swov.SWDevice.dwSWCrPhysicalAddr[0] =
   1218                     pVia->swov.SWDevice.dwSWPhysicalAddr[0] +
   1219                     (pitch * Height);
   1220             pVia->swov.SWDevice.dwSWCrPhysicalAddr[1] =
   1221                     pVia->swov.SWDevice.dwSWPhysicalAddr[1] +
   1222                     (pitch * Height);
   1223             pVia->swov.SWDevice.dwSWCbPhysicalAddr[0] =
   1224                     pVia->swov.SWDevice.dwSWCrPhysicalAddr[0] +
   1225                     ((pitch >> 1) * (Height >> 1));
   1226             pVia->swov.SWDevice.dwSWCbPhysicalAddr[1] =
   1227                     pVia->swov.SWDevice.dwSWCrPhysicalAddr[1] +
   1228                     ((pitch >> 1) * (Height >> 1));
   1229         }
   1230     }
   1231 
   1232     pVia->swov.SWDevice.gdwSWSrcWidth = Width;
   1233     pVia->swov.SWDevice.gdwSWSrcHeight = Height;
   1234     pVia->swov.SWDevice.dwPitch = pitch;
   1235 
   1236     pVia->swov.overlayRecordV1.dwV1OriWidth = Width;
   1237     pVia->swov.overlayRecordV1.dwV1OriHeight = Height;
   1238     pVia->swov.overlayRecordV1.dwV1OriPitch = pitch;
   1239 
   1240     return Success;
   1241 }
   1242 
   1243 /*
   1244  *
   1245  */
   1246 int
   1247 ViaSwovSurfaceCreate(ScrnInfoPtr pScrn, viaPortPrivPtr pPriv,
   1248                      CARD32 FourCC, CARD16 Width, CARD16 Height)
   1249 {
   1250     VIAPtr pVia = VIAPTR(pScrn);
   1251     unsigned long retCode = Success;
   1252     int numbuf = pVia->HWDiff.dwThreeHQVBuffer ? 3 : 2;
   1253 
   1254     DBG_DD(ErrorF("ViaSwovSurfaceCreate: FourCC =0x%08lx\n", FourCC));
   1255 
   1256     if ((pVia->VideoStatus & VIDEO_SWOV_SURFACE_CREATED)
   1257         && (FourCC == pPriv->FourCC))
   1258         return Success;
   1259 
   1260     pPriv->FourCC = FourCC;
   1261     switch (FourCC) {
   1262         case FOURCC_YUY2:
   1263         case FOURCC_RV15:
   1264         case FOURCC_RV16:
   1265         case FOURCC_RV32:
   1266             retCode = CreateSurface(pScrn, FourCC, Width, Height, TRUE);
   1267             if (retCode != Success)
   1268                 break;
   1269             if ((pVia->swov.gdwVideoFlagSW & SW_USE_HQV))
   1270                 retCode = AddHQVSurface(pScrn, numbuf, FourCC);
   1271             break;
   1272 
   1273         case FOURCC_HQVSW:
   1274             retCode = AddHQVSurface(pScrn, numbuf, FOURCC_YUY2);
   1275             break;
   1276 
   1277         case FOURCC_YV12:
   1278         case FOURCC_I420:
   1279             retCode = CreateSurface(pScrn, FourCC, Width, Height, TRUE);
   1280             if (retCode == Success)
   1281                 retCode = AddHQVSurface(pScrn, numbuf, FourCC);
   1282             break;
   1283 
   1284         case FOURCC_XVMC:
   1285             retCode = CreateSurface(pScrn, FourCC, Width, Height, FALSE);
   1286             if (retCode == Success)
   1287                 retCode = AddHQVSurface(pScrn, numbuf, FOURCC_XVMC);
   1288             break;
   1289 
   1290         default:
   1291             break;
   1292     }
   1293 
   1294     if (retCode == Success) {
   1295         DBG_DD(ErrorF(" lpSWOverlaySurface[0]: %p\n",
   1296                       pVia->swov.SWDevice.lpSWOverlaySurface[0]));
   1297         DBG_DD(ErrorF(" lpSWOverlaySurface[1]: %p\n",
   1298                       pVia->swov.SWDevice.lpSWOverlaySurface[1]));
   1299 
   1300         pVia->VideoStatus |= VIDEO_SWOV_SURFACE_CREATED | VIDEO_SWOV_ON;
   1301     }
   1302     return retCode;
   1303 }
   1304 
   1305 /*
   1306  *  Destroy Surface
   1307  */
   1308 void
   1309 ViaSwovSurfaceDestroy(ScrnInfoPtr pScrn, viaPortPrivPtr pPriv)
   1310 {
   1311     VIAPtr pVia = VIAPTR(pScrn);
   1312 
   1313     DBG_DD(ErrorF("ViaSwovSurfaceDestroy: FourCC =0x%08lx\n", pPriv->FourCC));
   1314 
   1315     if (pVia->VideoStatus & VIDEO_SWOV_SURFACE_CREATED) {
   1316         DBG_DD(ErrorF("ViaSwovSurfaceDestroy: VideoStatus =0x%08lx\n",
   1317                       pVia->VideoStatus));
   1318 
   1319         switch (pPriv->FourCC) {
   1320             case FOURCC_YUY2:
   1321             case FOURCC_RV16:
   1322             case FOURCC_RV32:
   1323             case FOURCC_RV15:
   1324                 pVia->swov.SrcFourCC = 0;
   1325 
   1326                 drm_bo_unmap(pScrn, pVia->swov.SWfbMem);
   1327                 drm_bo_free(pScrn, pVia->swov.SWfbMem);
   1328                 if ((pVia->swov.gdwVideoFlagSW & SW_USE_HQV)) {
   1329                     drm_bo_unmap(pScrn, pVia->swov.HQVMem);
   1330                     drm_bo_free(pScrn, pVia->swov.HQVMem);
   1331                 }
   1332                 pVia->swov.gdwVideoFlagSW = 0;
   1333                 break;
   1334 
   1335             case FOURCC_HQVSW:
   1336                 drm_bo_free(pScrn, pVia->swov.HQVMem);
   1337                 pVia->swov.gdwVideoFlagSW = 0;
   1338                 break;
   1339 
   1340             case FOURCC_YV12:
   1341             case FOURCC_I420:
   1342                 drm_bo_unmap(pScrn, pVia->swov.SWfbMem);
   1343                 drm_bo_free(pScrn, pVia->swov.SWfbMem);
   1344             case FOURCC_XVMC:
   1345                 pVia->swov.SrcFourCC = 0;
   1346 
   1347                 drm_bo_free(pScrn, pVia->swov.HQVMem);
   1348                 pVia->swov.gdwVideoFlagSW = 0;
   1349                 break;
   1350         }
   1351 
   1352         pPriv->FourCC = 0;
   1353         pVia->VideoStatus &= ~VIDEO_SWOV_SURFACE_CREATED;
   1354 
   1355     } else
   1356         DBG_DD(ErrorF("ViaSwovSurfaceDestroy: No SW Surface Destroyed, "
   1357                       "VideoStatus =0x%08lx\n", pVia->VideoStatus));
   1358 }
   1359 
   1360 static void
   1361 SetFIFO_V1(VIAPtr pVia, CARD8 depth, CARD8 prethreshold, CARD8 threshold)
   1362 {
   1363     SaveVideoRegister(pVia, V_FIFO_CONTROL,
   1364                       ((depth - 1) & 0x7f) |
   1365                       ((prethreshold & 0x7f) << 24) |
   1366                       ((threshold & 0x7f) << 8));
   1367 }
   1368 
   1369 static void
   1370 SetFIFO_V3(VIAPtr pVia, CARD8 depth, CARD8 prethreshold, CARD8 threshold)
   1371 {
   1372     switch (pVia->ChipId) {
   1373         case PCI_CHIP_VT3314:
   1374         case PCI_CHIP_VT3324:
   1375         case PCI_CHIP_VT3327:
   1376         case PCI_CHIP_VT3353:
   1377         case PCI_CHIP_VT3409:
   1378         case PCI_CHIP_VT3410:
   1379             SaveVideoRegister(pVia, ALPHA_V3_FIFO_CONTROL,
   1380                               (VIAGETREG(ALPHA_V3_FIFO_CONTROL) & ALPHA_FIFO_MASK)
   1381                                | ((depth - 1) & 0xff) | ((threshold & 0xff) << 8));
   1382             SaveVideoRegister(pVia, ALPHA_V3_PREFIFO_CONTROL,
   1383                               (VIAGETREG(ALPHA_V3_PREFIFO_CONTROL)
   1384                               & ~V3_FIFO_MASK_3314) | (prethreshold & 0xff));
   1385             break;
   1386         default :
   1387             SaveVideoRegister(pVia, ALPHA_V3_FIFO_CONTROL,
   1388                               (VIAGETREG(ALPHA_V3_FIFO_CONTROL) & ALPHA_FIFO_MASK)
   1389                               | ((depth - 1) & 0xff) | ((threshold & 0xff) << 8));
   1390             SaveVideoRegister(pVia, ALPHA_V3_PREFIFO_CONTROL,
   1391                               (VIAGETREG(ALPHA_V3_PREFIFO_CONTROL) & ~V3_FIFO_MASK)
   1392                               | (prethreshold & 0x7f));
   1393             break;
   1394     }
   1395 }
   1396 
   1397 static void
   1398 SetFIFO_64or32(VIAPtr pVia)
   1399 {
   1400     /*=* Modify for C1 FIFO *=*/
   1401     /* WARNING: not checking Chipset! */
   1402     if (CLE266_REV_IS_CX(pVia->ChipRev))
   1403         SetFIFO_V1(pVia, 64, 56, 56);
   1404     else
   1405         SetFIFO_V1(pVia, 32, 29, 16);
   1406 }
   1407 
   1408 static void
   1409 SetFIFO_64or16(VIAPtr pVia)
   1410 {
   1411     /*=* Modify for C1 FIFO *=*/
   1412     /* WARNING: not checking Chipset! */
   1413     if (CLE266_REV_IS_CX(pVia->ChipRev))
   1414         SetFIFO_V1(pVia, 64, 56, 56);
   1415     else
   1416         SetFIFO_V1(pVia, 16, 12, 8);
   1417 }
   1418 
   1419 static void
   1420 SetFIFO_64or48or32(VIAPtr pVia)
   1421 {
   1422     /*=* Modify for C1 FIFO *=*/
   1423     /* WARNING: not checking Chipset! */
   1424     if (CLE266_REV_IS_CX(pVia->ChipRev))
   1425         SetFIFO_V1(pVia, 64, 56, 56);
   1426     else {
   1427         if (pVia->swov.gdwUseExtendedFIFO)
   1428             SetFIFO_V1(pVia, 48, 40, 40);
   1429         else
   1430             SetFIFO_V1(pVia, 32, 29, 16);
   1431     }
   1432 }
   1433 
   1434 static void
   1435 SetFIFO_V3_64or32or32(VIAPtr pVia)
   1436 {
   1437     switch (pVia->ChipId) {
   1438         case PCI_CHIP_VT3327:
   1439         case PCI_CHIP_VT3336:
   1440         case PCI_CHIP_VT3324:
   1441         case PCI_CHIP_VT3364:
   1442         case PCI_CHIP_VT3353:
   1443         case PCI_CHIP_VT3409:
   1444         case PCI_CHIP_VT3410:
   1445             SetFIFO_V3(pVia, 225, 200, 250);
   1446             break;
   1447         case PCI_CHIP_VT3204:
   1448             SetFIFO_V3(pVia, 100, 89, 89);
   1449             break;
   1450         case PCI_CHIP_VT3314:
   1451             SetFIFO_V3(pVia, 64, 61, 61);
   1452             break;
   1453         case PCI_CHIP_VT3205:
   1454         case PCI_CHIP_VT3259:
   1455             SetFIFO_V3(pVia, 32, 29, 29);
   1456             break;
   1457         case PCI_CHIP_CLE3122:
   1458             if (CLE266_REV_IS_CX(pVia->ChipRev))
   1459                 SetFIFO_V3(pVia, 64, 56, 56);
   1460             else
   1461                 SetFIFO_V3(pVia, 32, 16, 16);
   1462             break;
   1463         default:
   1464             break;
   1465     }
   1466 }
   1467 
   1468 static void
   1469 SetFIFO_V3_64or32or16(VIAPtr pVia)
   1470 {
   1471     switch (pVia->ChipId) {
   1472         case PCI_CHIP_VT3327:
   1473         case PCI_CHIP_VT3336:
   1474         case PCI_CHIP_VT3324:
   1475         case PCI_CHIP_VT3364:
   1476         case PCI_CHIP_VT3353:
   1477         case PCI_CHIP_VT3409:
   1478         case PCI_CHIP_VT3410:
   1479             SetFIFO_V3(pVia, 225, 200, 250);
   1480             break;
   1481         case PCI_CHIP_VT3204:
   1482             SetFIFO_V3(pVia, 100, 89, 89);
   1483             break;
   1484         case PCI_CHIP_VT3314:
   1485             SetFIFO_V3(pVia, 64, 61, 61);
   1486             break;
   1487         case PCI_CHIP_VT3205:
   1488         case PCI_CHIP_VT3259:
   1489             SetFIFO_V3(pVia, 32, 29, 29);
   1490             break;
   1491 
   1492         case PCI_CHIP_CLE3122:
   1493             if (CLE266_REV_IS_CX(pVia->ChipRev))
   1494                 SetFIFO_V3(pVia, 64, 56, 56);
   1495             else
   1496                 SetFIFO_V3(pVia, 16, 16, 8);
   1497             break;
   1498 
   1499         default:
   1500             break;
   1501     }
   1502 }
   1503 
   1504 static void
   1505 SetupFIFOs(VIAPtr pVia, unsigned long videoFlag,
   1506            unsigned long miniCtl, unsigned long srcWidth)
   1507 {
   1508     if (miniCtl & V1_Y_INTERPOLY) {
   1509         if (pVia->swov.SrcFourCC == FOURCC_YV12
   1510             || pVia->swov.SrcFourCC == FOURCC_I420
   1511             || pVia->swov.SrcFourCC == FOURCC_XVMC) {
   1512             if (videoFlag & VIDEO_HQV_INUSE) {
   1513                 if (videoFlag & VIDEO_1_INUSE)
   1514                     SetFIFO_64or32(pVia);
   1515                 else
   1516                     SetFIFO_V3_64or32or16(pVia);
   1517             } else {
   1518                 /* Minified video will be skewed without this workaround. */
   1519                 if (srcWidth <= 80) { /* Fetch count <= 5 */
   1520                     if (videoFlag & VIDEO_1_INUSE)
   1521                         SetFIFO_V1(pVia, 16, 0, 0);
   1522                     else
   1523                         SetFIFO_V3(pVia, 16, 16, 0);
   1524                 } else {
   1525                     if (videoFlag & VIDEO_1_INUSE)
   1526                         SetFIFO_64or16(pVia);
   1527                     else
   1528                         SetFIFO_V3_64or32or16(pVia);
   1529                 }
   1530             }
   1531         } else {
   1532             if (videoFlag & VIDEO_1_INUSE)
   1533                 SetFIFO_64or48or32(pVia);
   1534             else {
   1535                 /* Fix V3 bug. */
   1536                 if (srcWidth <= 8)
   1537                     SetFIFO_V3(pVia, 1, 0, 0);
   1538                 else
   1539                     SetFIFO_V3_64or32or32(pVia);
   1540             }
   1541         }
   1542     } else {
   1543         if (pVia->swov.SrcFourCC == FOURCC_YV12
   1544             || pVia->swov.SrcFourCC == FOURCC_I420
   1545             || pVia->swov.SrcFourCC == FOURCC_XVMC) {
   1546             if (videoFlag & VIDEO_HQV_INUSE) {
   1547                 if (videoFlag & VIDEO_1_INUSE)
   1548                     SetFIFO_64or32(pVia);
   1549                 else
   1550                     SetFIFO_V3_64or32or16(pVia);
   1551             } else {
   1552                 /* Minified video will be skewed without this workaround. */
   1553                 if (srcWidth <= 80) { /* Fetch count <= 5 */
   1554                     if (videoFlag & VIDEO_1_INUSE)
   1555                         SetFIFO_V1(pVia, 16, 0, 0);
   1556                     else
   1557                         SetFIFO_V3(pVia, 16, 16, 0);
   1558                 } else {
   1559                     if (videoFlag & VIDEO_1_INUSE)
   1560                         SetFIFO_64or16(pVia);
   1561                     else
   1562                         SetFIFO_V3_64or32or16(pVia);
   1563                 }
   1564             }
   1565         } else {
   1566             if (videoFlag & VIDEO_1_INUSE)
   1567                 SetFIFO_64or48or32(pVia);
   1568             else {
   1569                 /* Fix V3 bug. */
   1570                 if (srcWidth <= 8)
   1571                     SetFIFO_V3(pVia, 1, 0, 0);
   1572                 else
   1573                     SetFIFO_V3_64or32or32(pVia);
   1574             }
   1575         }
   1576     }
   1577 }
   1578 
   1579 static CARD32
   1580 SetColorKey(VIAPtr pVia, unsigned long videoFlag,
   1581             CARD32 keyLow, CARD32 keyHigh, CARD32 compose)
   1582 {
   1583     keyLow &= 0x00FFFFFF;
   1584     if (pVia->VideoEngine == VIDEO_ENGINE_CME)
   1585         keyLow |= 0x40000000;
   1586 
   1587     if (videoFlag & VIDEO_1_INUSE) {
   1588         SaveVideoRegister(pVia, V_COLOR_KEY, keyLow);
   1589         SaveVideoRegister(pVia, SND_COLOR_KEY, keyLow);
   1590     } else {
   1591         if (pVia->HWDiff.dwSupportTwoColorKey)    /*CLE_C0 */
   1592             SaveVideoRegister(pVia, V3_COLOR_KEY, keyLow);
   1593     }
   1594 
   1595     /*CLE_C0 */
   1596     compose = ((compose & ~0x0f) | SELECT_VIDEO_IF_COLOR_KEY |
   1597                SELECT_VIDEO3_IF_COLOR_KEY);
   1598 
   1599     return compose;
   1600 }
   1601 
   1602 static CARD32
   1603 SetChromaKey(VIAPtr pVia, unsigned long videoFlag,
   1604              CARD32 chromaLow, CARD32 chromaHigh,
   1605              CARD32 miniCtl, CARD32 compose)
   1606 {
   1607     chromaLow &= CHROMA_KEY_LOW;
   1608     chromaHigh &= CHROMA_KEY_HIGH;
   1609 
   1610     chromaLow |= (VIAGETREG(V_CHROMAKEY_LOW) & ~CHROMA_KEY_LOW);
   1611     chromaHigh |= (VIAGETREG(V_CHROMAKEY_HIGH) & ~CHROMA_KEY_HIGH);
   1612 
   1613     if (pVia->VideoEngine == VIDEO_ENGINE_CME)
   1614         chromaLow |= 0x40000000;
   1615 
   1616     SaveVideoRegister(pVia, V_CHROMAKEY_HIGH, chromaHigh);
   1617     if (videoFlag & VIDEO_1_INUSE) {
   1618         SaveVideoRegister(pVia, V_CHROMAKEY_LOW, chromaLow & ~V_CHROMAKEY_V3);
   1619         /* Temporarily solve the HW interpolation error when using Chroma key */
   1620         SaveVideoRegister(pVia, V1_MINI_CONTROL, miniCtl & 0xFFFFFFF8);
   1621     } else {
   1622         SaveVideoRegister(pVia, V_CHROMAKEY_LOW, chromaLow | V_CHROMAKEY_V3);
   1623         SaveVideoRegister(pVia, V3_MINI_CONTROL, miniCtl & 0xFFFFFFF8);
   1624     }
   1625 
   1626     /* Modified by Scottie[2001.12.5] for select video if (Color key & Chroma key) */
   1627     if (compose == SELECT_VIDEO_IF_COLOR_KEY)
   1628         compose = SELECT_VIDEO_IF_COLOR_KEY | SELECT_VIDEO_IF_CHROMA_KEY;
   1629     else
   1630         compose = (compose & ~0x0f) | SELECT_VIDEO_IF_CHROMA_KEY;
   1631 
   1632     return compose;
   1633 }
   1634 
   1635 static void
   1636 SetVideoStart(VIAPtr pVia, unsigned long videoFlag,
   1637               unsigned int numbufs, CARD32 a1, CARD32 a2, CARD32 a3)
   1638 {
   1639     CARD32 V1Addr[3] = { V1_STARTADDR_0, V1_STARTADDR_1, V1_STARTADDR_2 };
   1640     CARD32 V3Addr[3] = { V3_STARTADDR_0, V3_STARTADDR_1, V3_STARTADDR_2 };
   1641     CARD32 *VideoAddr = (videoFlag & VIDEO_1_INUSE) ? V1Addr : V3Addr;
   1642 
   1643     SaveVideoRegister(pVia, VideoAddr[0], a1);
   1644     if (numbufs > 1)
   1645         SaveVideoRegister(pVia, VideoAddr[1], a2);
   1646     if (numbufs > 2)
   1647         SaveVideoRegister(pVia, VideoAddr[2], a3);
   1648 }
   1649 
   1650 static void
   1651 SetHQVFetch(VIAPtr pVia, CARD32 srcFetch, unsigned long srcHeight)
   1652 {
   1653     unsigned long proReg = 0;
   1654 
   1655     if (pVia->ChipId == PCI_CHIP_VT3259
   1656         && !(pVia->swov.gdwVideoFlagSW & VIDEO_1_INUSE))
   1657         proReg = PRO_HQV1_OFFSET;
   1658 
   1659     if (!pVia->HWDiff.dwHQVFetchByteUnit) {    /* CLE_C0 */
   1660         srcFetch >>= 3;  /* fetch unit is 8 bytes */
   1661     }
   1662 
   1663     if ((pVia->ChipId != PCI_CHIP_VT3409) && (pVia->ChipId != PCI_CHIP_VT3410))
   1664         SaveVideoRegister(pVia, HQV_SRC_FETCH_LINE + proReg,
   1665                           ((srcFetch - 1) << 16) | (srcHeight - 1));
   1666 }
   1667 
   1668 static void
   1669 SetFetch(VIAPtr pVia, unsigned long videoFlag, CARD32 fetch)
   1670 {
   1671     fetch <<= 20;
   1672     if (videoFlag & VIDEO_1_INUSE) {
   1673         SaveVideoRegister(pVia, V12_QWORD_PER_LINE, fetch);
   1674     } else {
   1675         fetch |= VIAGETREG(V3_ALPHA_QWORD_PER_LINE) & ~V3_FETCH_COUNT;
   1676         SaveVideoRegister(pVia, V3_ALPHA_QWORD_PER_LINE, fetch);
   1677     }
   1678 }
   1679 
   1680 static void
   1681 SetDisplayCount(VIAPtr pVia, unsigned long videoFlag,
   1682                 unsigned long srcWidth, unsigned long srcHeight)
   1683 {
   1684     unsigned long DisplayCount;
   1685 
   1686     /* Removed VIA's large pixelformat switch/case.
   1687      * All formats (YV12, UYVY, YUY2, VIA, RGB16 and RGB32)
   1688      * seem to use the same count. /A
   1689      */
   1690 
   1691     if (videoFlag & VIDEO_HQV_INUSE)
   1692         DisplayCount = srcWidth - 1;
   1693     else
   1694         DisplayCount = srcWidth - pVia->swov.overlayRecordV1.dwminifyH;
   1695 
   1696     if (videoFlag & VIDEO_1_INUSE)
   1697         SaveVideoRegister(pVia, V1_SOURCE_HEIGHT,
   1698                           (srcHeight << 16) | DisplayCount);
   1699     else
   1700         SaveVideoRegister(pVia, V3_SOURCE_WIDTH, DisplayCount);
   1701 }
   1702 
   1703 static void
   1704 SetMiniAndZoom(VIAPtr pVia, unsigned long videoFlag,
   1705                CARD32 miniCtl, CARD32 zoomCtl)
   1706 {
   1707     if (videoFlag & VIDEO_1_INUSE) {
   1708         SaveVideoRegister(pVia, V1_MINI_CONTROL, miniCtl);
   1709         SaveVideoRegister(pVia, V1_ZOOM_CONTROL, zoomCtl);
   1710     } else {
   1711         SaveVideoRegister(pVia, V3_MINI_CONTROL, miniCtl);
   1712         SaveVideoRegister(pVia, V3_ZOOM_CONTROL, zoomCtl);
   1713     }
   1714 }
   1715 
   1716 static void
   1717 SetVideoControl(VIAPtr pVia, unsigned long videoFlag, CARD32 vidCtl)
   1718 {
   1719     if (videoFlag & VIDEO_1_INUSE)
   1720         SaveVideoRegister(pVia, V1_CONTROL, vidCtl);
   1721     else
   1722         SaveVideoRegister(pVia, V3_CONTROL, vidCtl);
   1723 }
   1724 
   1725 static void
   1726 FireVideoCommand(VIAPtr pVia, unsigned long videoFlag, CARD32 compose)
   1727 {
   1728     if (videoFlag & VIDEO_1_INUSE)
   1729         SaveVideoRegister(pVia, V_COMPOSE_MODE, compose | V1_COMMAND_FIRE);
   1730     else
   1731         SaveVideoRegister(pVia, V_COMPOSE_MODE, compose | V3_COMMAND_FIRE);
   1732 }
   1733 
   1734 static void
   1735 SetVideoWindow(ScrnInfoPtr pScrn, unsigned long videoFlag,
   1736                LPDDUPDATEOVERLAY pUpdate)
   1737 {
   1738     VIAPtr pVia = VIAPTR(pScrn);
   1739     CARD32 left = pUpdate->DstLeft;
   1740     CARD32 top = pUpdate->DstTop;
   1741     CARD32 right = pUpdate->DstRight - 1;
   1742     CARD32 bottom = pUpdate->DstBottom - 1;
   1743 
   1744     DBG_DD(ErrorF("SetVideoWindow: X (%ld,%ld) Y (%ld,%ld)\n",
   1745                   left, right, top, bottom));
   1746 
   1747     /* Modify for HW DVI limitation.
   1748      * When we enable both the CRT and DVI, then change resolution.
   1749      * If the resolution is smaller than the panel's physical size,
   1750      * the video display in Y direction will be cut.
   1751      * So, we need to adjust the Y top and bottom position.
   1752      *
   1753     if (videoFlag & VIDEO_1_INUSE) {
   1754         if (pBIOSInfo->SetDVI && pBIOSInfo->scaleY) {
   1755             top = (pUpdate->DstTop * pBIOSInfo->Panel->NativeMode->Height
   1756                    / pScrn->currentMode->VDisplay);
   1757             bottom = (pUpdate->DstBottom * pBIOSInfo->Panel->NativeMode->Height
   1758                       / pScrn->currentMode->VDisplay);
   1759         }
   1760     }*/
   1761 
   1762     if (top > 2047)
   1763         top = 2047;
   1764 
   1765     if (bottom > 2047)
   1766         bottom = 2047;
   1767 
   1768     if (left > 2047)
   1769         left = 2047;
   1770 
   1771     if (right > 2047)
   1772         right = 2047;
   1773 
   1774     if (videoFlag & VIDEO_1_INUSE) {
   1775         SaveVideoRegister(pVia, V1_WIN_END_Y, (right << 16) | bottom);
   1776         SaveVideoRegister(pVia, V1_WIN_START_Y, (left << 16) | top);
   1777     } else {
   1778         SaveVideoRegister(pVia, V3_WIN_END_Y, (right << 16) | bottom);
   1779         SaveVideoRegister(pVia, V3_WIN_START_Y, (left << 16) | top);
   1780     }
   1781 }
   1782 
   1783 /*
   1784  * Upd_Video()
   1785  */
   1786 static Bool
   1787 Upd_Video(xf86CrtcPtr crtc, unsigned long videoFlag,
   1788           unsigned long startAddr, LPDDUPDATEOVERLAY pUpdate,
   1789           unsigned long srcPitch,
   1790           unsigned long oriSrcWidth, unsigned long oriSrcHeight,
   1791           unsigned long deinterlaceMode,
   1792           unsigned long haveColorKey, unsigned long haveChromaKey,
   1793           unsigned long colorKeyLow, unsigned long colorKeyHigh,
   1794           unsigned long chromaKeyLow, unsigned long chromaKeyHigh)
   1795 {
   1796     drmmode_crtc_private_ptr iga = crtc->driver_private;
   1797     ScrnInfoPtr pScrn = crtc->scrn;
   1798     VIAPtr pVia = VIAPTR(pScrn);
   1799     vgaHWPtr hwp = VGAHWPTR(pScrn);
   1800     VIAHWDiff *hwDiff = &pVia->HWDiff;
   1801     unsigned long vidCtl = 0, compose;
   1802     unsigned long srcWidth, srcHeight, dstWidth, dstHeight;
   1803     unsigned long zoomCtl = 0, miniCtl = 0;
   1804     unsigned long hqvCtl = 0;
   1805     unsigned long hqvFilterCtl = 0, hqvMiniCtl = 0;
   1806     unsigned long hqvScaleCtlH = 0, hqvScaleCtlV = 0;
   1807     unsigned long haveHQVzoomH = 0, haveHQVzoomV = 0;
   1808     unsigned long hqvSrcWidth = 0, hqvDstWidth = 0;
   1809     unsigned long hqvSrcFetch = 0, hqvOffset = 0;
   1810     unsigned long dwOffset = 0, fetch = 0, tmp = 0;
   1811     unsigned long proReg = 0;
   1812     int i;
   1813 
   1814     DBG_DD(ErrorF("videoflag=%ld\n", videoFlag));
   1815 
   1816     if (pVia->ChipId == PCI_CHIP_VT3259 && !(videoFlag & VIDEO_1_INUSE))
   1817         proReg = PRO_HQV1_OFFSET;
   1818 
   1819     compose = ((VIAGETREG(V_COMPOSE_MODE)
   1820                 & ~(SELECT_VIDEO_IF_COLOR_KEY
   1821                     | V1_COMMAND_FIRE | V3_COMMAND_FIRE))
   1822                | V_COMMAND_LOAD_VBI);
   1823 
   1824     DBG_DD(ErrorF("// Upd_Video:\n"));
   1825     DBG_DD(ErrorF("Modified rSrc  X (%ld,%ld) Y (%ld,%ld)\n",
   1826                   pUpdate->SrcLeft, pUpdate->SrcRight,
   1827                   pUpdate->SrcTop, pUpdate->SrcBottom));
   1828     DBG_DD(ErrorF("Modified rDest  X (%ld,%ld) Y (%ld,%ld)\n",
   1829                   pUpdate->DstLeft, pUpdate->DstRight,
   1830                   pUpdate->DstTop, pUpdate->DstBottom));
   1831 
   1832     dstWidth = pUpdate->DstRight - pUpdate->DstLeft;
   1833 	/*if (pBIOSInfo->lvds && pBIOSInfo->lvds->status == XF86OutputStatusConnected &&
   1834 		pBIOSInfo->Panel->Scale) {
   1835         * FIXME: We need to determine if the panel is using V1 or V3 *
   1836         float hfactor = (float)pBIOSInfo->Panel->NativeMode->Width
   1837                         / pScrn->currentMode->HDisplay;
   1838         dstWidth *= hfactor;
   1839     }*/
   1840 
   1841     pVia->swov.overlayRecordV1.dwWidth = dstWidth;
   1842     pVia->swov.overlayRecordV1.dwHeight = dstHeight =
   1843             pUpdate->DstBottom - pUpdate->DstTop;
   1844     srcWidth = (unsigned long)pUpdate->SrcRight - pUpdate->SrcLeft;
   1845     srcHeight = (unsigned long)pUpdate->SrcBottom - pUpdate->SrcTop;
   1846     DBG_DD(ErrorF("===srcWidth= %ld \n", srcWidth));
   1847     DBG_DD(ErrorF("===srcHeight= %ld \n", srcHeight));
   1848 
   1849     vidCtl = ViaSetVidCtl(pVia, videoFlag);
   1850 
   1851     if (hwDiff->dwNeedV1Prefetch) {
   1852         DBG_DD(ErrorF("NEEDV1PREFETCH\n"));
   1853         vidCtl |= V1_PREFETCH_ON_3336;
   1854     }
   1855 
   1856     /*
   1857      * Enable video on secondary
   1858      */
   1859     if ((pVia->VideoEngine == VIDEO_ENGINE_CME ||
   1860          pVia->Chipset == VIA_P4M800PRO) && iga->index) {
   1861         /* V1_ON_SND_DISPLAY */
   1862         vidCtl |= V1_ON_SND_DISPLAY;
   1863         /* SECOND_DISPLAY_COLOR_KEY_ENABLE */
   1864         compose |= SECOND_DISPLAY_COLOR_KEY_ENABLE | 0x1;
   1865     }
   1866 
   1867     viaOverlayGetV1V3Format(pVia, (videoFlag & VIDEO_1_INUSE) ? 1 : 3,
   1868                             videoFlag, &vidCtl, &hqvCtl);
   1869 
   1870     if (hwDiff->dwThreeHQVBuffer) {    /* CLE_C0: HQV supports triple-buffering */
   1871         hqvCtl &= ~HQV_SW_FLIP;
   1872         hqvCtl |= HQV_TRIPLE_BUFF | HQV_FLIP_STATUS;
   1873     }
   1874 
   1875     /* Starting address of source and Source offset */
   1876     dwOffset = viaOverlayGetSrcStartAddress(pVia, videoFlag, pUpdate,
   1877                                             srcPitch, &hqvOffset);
   1878     DBG_DD(ErrorF("===dwOffset= 0x%lx \n", dwOffset));
   1879 
   1880     pVia->swov.overlayRecordV1.dwOffset = dwOffset;
   1881 
   1882     if (pVia->swov.SrcFourCC == FOURCC_YV12
   1883         || pVia->swov.SrcFourCC == FOURCC_I420
   1884         || pVia->swov.SrcFourCC == FOURCC_XVMC) {
   1885 
   1886         YCBCRREC YCbCr;
   1887 
   1888         if (videoFlag & VIDEO_HQV_INUSE) {
   1889             SetVideoStart(pVia, videoFlag, hwDiff->dwThreeHQVBuffer ? 3 : 2,
   1890                           pVia->swov.overlayRecordV1.dwHQVAddr[0] + dwOffset,
   1891                           pVia->swov.overlayRecordV1.dwHQVAddr[1] + dwOffset,
   1892                           pVia->swov.overlayRecordV1.dwHQVAddr[2] + dwOffset);
   1893 
   1894             if (pVia->swov.SrcFourCC != FOURCC_XVMC) {
   1895                 YCbCr = viaOverlayGetYCbCrStartAddress(videoFlag, startAddr,
   1896                                 pVia->swov.overlayRecordV1.dwOffset,
   1897                                 pVia->swov.overlayRecordV1.dwUVoffset,
   1898                                 srcPitch, oriSrcHeight);
   1899                 if (pVia->VideoEngine == VIDEO_ENGINE_CME) {
   1900                     SaveVideoRegister(pVia, HQV_SRC_STARTADDR_Y + proReg,
   1901                                       YCbCr.dwY);
   1902                     SaveVideoRegister(pVia, HQV_SRC_STARTADDR_U + proReg,
   1903                                       YCbCr.dwCB);
   1904                 } else {
   1905                     SaveVideoRegister(pVia, HQV_SRC_STARTADDR_Y, YCbCr.dwY);
   1906                     SaveVideoRegister(pVia, HQV_SRC_STARTADDR_U, YCbCr.dwCR);
   1907                     SaveVideoRegister(pVia, HQV_SRC_STARTADDR_V, YCbCr.dwCB);
   1908                 }
   1909             }
   1910         } else {
   1911             YCbCr = viaOverlayGetYCbCrStartAddress(videoFlag, startAddr,
   1912                             pVia->swov.overlayRecordV1.dwOffset,
   1913                             pVia->swov.overlayRecordV1.dwUVoffset,
   1914                             srcPitch, oriSrcHeight);
   1915 
   1916             if (videoFlag & VIDEO_1_INUSE) {
   1917                 SaveVideoRegister(pVia, V1_STARTADDR_0, YCbCr.dwY);
   1918                 SaveVideoRegister(pVia, V1_STARTADDR_CB0, YCbCr.dwCR);
   1919                 SaveVideoRegister(pVia, V1_STARTADDR_CR0, YCbCr.dwCB);
   1920             } else
   1921                 DBG_DD(ErrorF("Upd_Video(): "
   1922                               "We do not support YV12 with V3!\n"));
   1923         }
   1924     } else {
   1925         if (videoFlag & VIDEO_HQV_INUSE) {
   1926             hqvSrcWidth = (unsigned long)pUpdate->SrcRight - pUpdate->SrcLeft;
   1927             hqvDstWidth = (unsigned long)pUpdate->DstRight - pUpdate->DstLeft;
   1928 
   1929             if (hqvSrcWidth > hqvDstWidth)
   1930                 dwOffset = dwOffset * hqvDstWidth / hqvSrcWidth;
   1931 
   1932             SetVideoStart(pVia, videoFlag, hwDiff->dwThreeHQVBuffer ? 3 : 2,
   1933                           pVia->swov.overlayRecordV1.dwHQVAddr[0] + hqvOffset,
   1934                           pVia->swov.overlayRecordV1.dwHQVAddr[1] + hqvOffset,
   1935                           pVia->swov.overlayRecordV1.dwHQVAddr[2] + hqvOffset);
   1936 
   1937             if (pVia->VideoEngine == VIDEO_ENGINE_CME)
   1938                 SaveVideoRegister(pVia, 0x1cc + proReg, dwOffset);
   1939 
   1940             SaveVideoRegister(pVia, HQV_SRC_STARTADDR_Y + proReg, startAddr);
   1941         } else {
   1942             startAddr += dwOffset;
   1943             SetVideoStart(pVia, videoFlag, 1, startAddr, 0, 0);
   1944         }
   1945     }
   1946 
   1947     fetch = viaOverlayGetFetch(pVia, videoFlag,
   1948                                srcWidth, dstWidth, oriSrcWidth, &hqvSrcFetch);
   1949     DBG_DD(ErrorF("===fetch= 0x%lx\n", fetch));
   1950 
   1951 #if 0
   1952     /* For DCT450 test-BOB INTERLEAVE */
   1953     if ((deinterlaceMode & DDOVER_INTERLEAVED)
   1954         && (deinterlaceMode & DDOVER_BOB)) {
   1955         if (videoFlag & VIDEO_HQV_INUSE)
   1956             hqvCtl |= HQV_FIELD_2_FRAME | HQV_FRAME_2_FIELD | HQV_DEINTERLACE;
   1957         else
   1958             vidCtl |= V1_BOB_ENABLE | V1_FRAME_BASE;
   1959     } else if (deinterlaceMode & DDOVER_BOB) {
   1960         if (videoFlag & VIDEO_HQV_INUSE)
   1961             /* The HQV source data line count should be two times of the original line count */
   1962             hqvCtl |= HQV_FIELD_2_FRAME | HQV_DEINTERLACE;
   1963         else
   1964             vidCtl |= V1_BOB_ENABLE;
   1965     }
   1966 #endif
   1967 
   1968     if (videoFlag & VIDEO_HQV_INUSE) {
   1969         if (!(deinterlaceMode & DDOVER_INTERLEAVED)
   1970             && (deinterlaceMode & DDOVER_BOB))
   1971             SetHQVFetch(pVia, hqvSrcFetch, oriSrcHeight << 1);
   1972         else
   1973             SetHQVFetch(pVia, hqvSrcFetch, oriSrcHeight);
   1974 
   1975         if (pVia->swov.SrcFourCC == FOURCC_YV12
   1976             || pVia->swov.SrcFourCC == FOURCC_I420
   1977             || pVia->swov.SrcFourCC == FOURCC_XVMC) {
   1978             if (videoFlag & VIDEO_1_INUSE)
   1979                 SaveVideoRegister(pVia, V1_STRIDE, srcPitch << 1);
   1980             else
   1981                 SaveVideoRegister(pVia, V3_STRIDE, srcPitch << 1);
   1982 
   1983             if (pVia->HWDiff.dwHQVFetchByteUnit)
   1984                 SaveVideoRegister(pVia, HQV_SRC_STRIDE + proReg,
   1985                                   ((srcPitch >> 1) << 16) | srcPitch |
   1986                                   HQV_FIFO_DEPTH_1);
   1987             else
   1988                 SaveVideoRegister(pVia, HQV_SRC_STRIDE + proReg,
   1989                                   ((srcPitch >> 1) << 16) | srcPitch);
   1990 
   1991             SaveVideoRegister(pVia, HQV_DST_STRIDE + proReg, (srcPitch << 1));
   1992         } else {
   1993             if (videoFlag & VIDEO_1_INUSE)
   1994                 SaveVideoRegister(pVia, V1_STRIDE, srcPitch);
   1995             else
   1996                 SaveVideoRegister(pVia, V3_STRIDE, srcPitch);
   1997 
   1998             SaveVideoRegister(pVia, HQV_SRC_STRIDE + proReg, srcPitch);
   1999             SaveVideoRegister(pVia, HQV_DST_STRIDE + proReg, srcPitch);
   2000         }
   2001 
   2002     } else {
   2003         if (videoFlag & VIDEO_1_INUSE)
   2004             SaveVideoRegister(pVia, V1_STRIDE, srcPitch | (srcPitch << 15));
   2005         else
   2006             SaveVideoRegister(pVia, V3_STRIDE, srcPitch | (srcPitch << 15));
   2007     }
   2008 
   2009     /* Set destination window */
   2010     SetVideoWindow(pScrn, videoFlag, pUpdate);
   2011 
   2012     compose |= ALWAYS_SELECT_VIDEO;
   2013 
   2014     /* Set up X zoom factor */
   2015 
   2016     pVia->swov.overlayRecordV1.dwFetchAlignment = 0;
   2017 
   2018     if (!viaOverlayHQVCalcZoomWidth(pVia, videoFlag, srcWidth, dstWidth,
   2019                                     &zoomCtl, &miniCtl, &hqvFilterCtl,
   2020                                     &hqvMiniCtl, &hqvScaleCtlH, &haveHQVzoomH)) {
   2021         /* Need to scale (minify) too much - can't handle it. */
   2022         SetFetch(pVia, videoFlag, fetch);
   2023         FireVideoCommand(pVia, videoFlag, compose);
   2024         FlushVidRegBuffer(pVia);
   2025         return FALSE;
   2026     }
   2027 
   2028     SetFetch(pVia, videoFlag, fetch);
   2029 
   2030     /* Set up Y zoom factor */
   2031 
   2032     /* For DCT450 test-BOB INTERLEAVE */
   2033     if ((deinterlaceMode & DDOVER_INTERLEAVED)
   2034         && (deinterlaceMode & DDOVER_BOB)) {
   2035         if (!(videoFlag & VIDEO_HQV_INUSE)) {
   2036             srcHeight /= 2;
   2037             if (videoFlag & VIDEO_1_INUSE)
   2038                 vidCtl |= V1_BOB_ENABLE | V1_FRAME_BASE;
   2039             else
   2040                 vidCtl |= V3_BOB_ENABLE | V3_FRAME_BASE;
   2041         } else
   2042             hqvCtl |= HQV_FIELD_2_FRAME | HQV_FRAME_2_FIELD | HQV_DEINTERLACE;
   2043     } else if (deinterlaceMode & DDOVER_BOB) {
   2044         if (videoFlag & VIDEO_HQV_INUSE) {
   2045             srcHeight <<= 1;
   2046             hqvCtl |= HQV_FIELD_2_FRAME | HQV_DEINTERLACE;
   2047         } else {
   2048             if (videoFlag & VIDEO_1_INUSE)
   2049                 vidCtl |= V1_BOB_ENABLE;
   2050             else
   2051                 vidCtl |= V3_BOB_ENABLE;
   2052         }
   2053     }
   2054 
   2055     SetDisplayCount(pVia, videoFlag, srcWidth, srcHeight);
   2056 
   2057     if (!viaOverlayHQVCalcZoomHeight(pVia, srcHeight, dstHeight, &zoomCtl,
   2058                                      &miniCtl, &hqvFilterCtl, &hqvMiniCtl,
   2059                                      &hqvScaleCtlV, &haveHQVzoomV)) {
   2060         /* Need to scale (minify) too much - can't handle it. */
   2061         FireVideoCommand(pVia, videoFlag, compose);
   2062         FlushVidRegBuffer(pVia);
   2063         return FALSE;
   2064     }
   2065 
   2066     SetupFIFOs(pVia, videoFlag, miniCtl, srcWidth);
   2067 
   2068     if (videoFlag & VIDEO_HQV_INUSE) {
   2069         miniCtl = 0;
   2070 
   2071         if (haveHQVzoomH || haveHQVzoomV) {
   2072             tmp = 0;
   2073 
   2074             if (haveHQVzoomH) {
   2075                 miniCtl = V1_X_INTERPOLY;
   2076                 /* Disable X interpolation if the height exceeds
   2077                  * the maximum supported by the hardware */
   2078                 if (srcHeight >= pVia->swov.maxHInterp)
   2079                     miniCtl &= ~V1_X_INTERPOLY;
   2080                 tmp = zoomCtl & 0xffff0000;
   2081             }
   2082 
   2083             if (haveHQVzoomV) {
   2084                 miniCtl |= V1_Y_INTERPOLY | V1_YCBCR_INTERPOLY;
   2085                 /* Disable Y interpolation if the width exceeds
   2086                  * the maximum supported by the hardware */
   2087                 if (srcWidth >= pVia->swov.maxWInterp)
   2088                     miniCtl &= ~V1_Y_INTERPOLY;
   2089                 tmp |= zoomCtl & 0x0000ffff;
   2090                 hqvFilterCtl &= 0xfffdffff;
   2091             }
   2092 
   2093             /* Temporary fix for 2D bandwidth problem. 2002/08/01 */
   2094             if (pVia->swov.gdwUseExtendedFIFO)
   2095                 miniCtl &= ~V1_Y_INTERPOLY;
   2096 
   2097             SetMiniAndZoom(pVia, videoFlag, miniCtl, tmp);
   2098         } else {
   2099             if (srcHeight == dstHeight)
   2100                 hqvFilterCtl &= 0xfffdffff;
   2101             SetMiniAndZoom(pVia, videoFlag, 0, 0);
   2102         }
   2103 	if (hwDiff->dwNewScaleCtl) {
   2104 		SaveVideoRegister(pVia, HQV_H_SCALE_CONTROL + proReg, hqvScaleCtlH);
   2105 		SaveVideoRegister(pVia, HQV_V_SCALE_CONTROL + proReg, hqvScaleCtlV);
   2106 	} else {
   2107 		SaveVideoRegister(pVia, HQV_MINIFY_CONTROL + proReg, hqvMiniCtl);
   2108 	}
   2109 	SaveVideoRegister(pVia, HQV_FILTER_CONTROL + proReg, hqvFilterCtl);
   2110     } else
   2111         SetMiniAndZoom(pVia, videoFlag, miniCtl, zoomCtl);
   2112 
   2113     if (haveColorKey)
   2114         compose = SetColorKey(pVia, videoFlag, colorKeyLow, colorKeyHigh,
   2115                               compose);
   2116 
   2117     if (haveChromaKey)
   2118         compose = SetChromaKey(pVia, videoFlag, chromaKeyLow, chromaKeyHigh,
   2119                                miniCtl, compose);
   2120 
   2121     if (pVia->VideoEngine == VIDEO_ENGINE_CME) {
   2122         SaveVideoRegister(pVia, HQV_CME_REG(hwDiff, HQV_SDO_CTRL1),0);
   2123         SaveVideoRegister(pVia, HQV_CME_REG(hwDiff, HQV_SDO_CTRL3),((pUpdate->SrcRight - 1 ) << 16) | (pUpdate->SrcBottom - 1));
   2124         if ((pVia->Chipset == VIA_VX800) ||
   2125             (pVia->Chipset == VIA_VX855) ||
   2126             (pVia->Chipset == VIA_VX900)) {
   2127             SaveVideoRegister(pVia, HQV_CME_REG(hwDiff, HQV_SDO_CTRL2),0);
   2128             SaveVideoRegister(pVia, HQV_CME_REG(hwDiff, HQV_SDO_CTRL4),((pUpdate->SrcRight - 1 ) << 16) | (pUpdate->SrcBottom - 1));
   2129             if ((pVia->Chipset == VIA_VX855) ||
   2130                 (pVia->Chipset == VIA_VX900)) {
   2131                 SaveVideoRegister(pVia, HQV_DST_DATA_OFFSET_CTRL1,0);
   2132                 SaveVideoRegister(pVia, HQV_DST_DATA_OFFSET_CTRL3,((pUpdate->SrcRight - 1 ) << 16) | (pUpdate->SrcBottom - 1));
   2133                 SaveVideoRegister(pVia, HQV_DST_DATA_OFFSET_CTRL2,0);
   2134                 SaveVideoRegister(pVia, HQV_DST_DATA_OFFSET_CTRL4,((pUpdate->SrcRight - 1 ) << 16) | (pUpdate->SrcBottom - 1));
   2135                 SaveVideoRegister(pVia, HQV_BACKGROUND_DATA_OFFSET,((pUpdate->SrcRight - 1 ) << 16) | (pUpdate->SrcBottom - 1));
   2136                 SaveVideoRegister(pVia, HQV_EXTENDED_CONTROL,0);
   2137                 /*0x3e0*/
   2138                 SaveVideoRegister(pVia, HQV_SUBP_HSCALE_CTRL,0);
   2139                 /*0x3e8*/
   2140                 SaveVideoRegister(pVia, HQV_SUBP_VSCALE_CTRL,0);
   2141             }
   2142 
   2143             if (pVia->Chipset == VIA_VX900) {
   2144 
   2145                 SaveVideoRegister(pVia, HQV_SHARPNESS_DECODER_HANDSHAKE_CTRL_410, 0);
   2146             }
   2147 
   2148             // TODO Need to be tested on VX800
   2149             /* 0x3B8 */
   2150             SaveVideoRegister(pVia, HQV_DEFAULT_VIDEO_COLOR, HQV_FIX_COLOR);
   2151 
   2152         }
   2153     }
   2154 
   2155     /* Set up video control */
   2156     if (videoFlag & VIDEO_HQV_INUSE) {
   2157 
   2158         if (!pVia->swov.SWVideo_ON) {
   2159             DBG_DD(ErrorF("    First HQV\n"));
   2160 
   2161             FlushVidRegBuffer(pVia);
   2162 
   2163             DBG_DD(ErrorF(" Wait flips"));
   2164 
   2165             if (hwDiff->dwHQVInitPatch) {
   2166                 DBG_DD(ErrorF(" Initializing HQV twice ..."));
   2167                 for (i = 0; i < 2; i++) {
   2168                     viaWaitHQVFlipClear(pVia,
   2169                                         ((hqvCtl & ~HQV_SW_FLIP) |
   2170                                          HQV_FLIP_STATUS) & ~HQV_ENABLE);
   2171                     VIASETREG(HQV_CONTROL + proReg, hqvCtl);
   2172                     viaWaitHQVFlip(pVia);
   2173                 }
   2174                 DBG_DD(ErrorF(" done.\n"));
   2175             } else {               /* CLE_C0 */
   2176                 CARD32 volatile *HQVCtrl =
   2177                         (CARD32 volatile *)(pVia->MapBase + HQV_CONTROL +
   2178                                             proReg);
   2179 
   2180                 /* Check that HQV is idle */
   2181                 DBG_DD(ErrorF("HQV control wf - %08lx\n", *HQVCtrl));
   2182                 while (!(*HQVCtrl & HQV_IDLE)) {
   2183                     DBG_DD(ErrorF("HQV control busy - %08lx\n", *HQVCtrl));
   2184                     usleep(1);
   2185                 }
   2186 
   2187                 VIASETREG(HQV_CONTROL + proReg, hqvCtl & ~HQV_SW_FLIP);
   2188                 VIASETREG(HQV_CONTROL + proReg, hqvCtl | HQV_SW_FLIP);
   2189 
   2190                 DBG_DD(ErrorF("HQV control wf5 - %08lx\n", *HQVCtrl));
   2191                 DBG_DD(ErrorF(" Wait flips5"));
   2192 
   2193                 if (pVia->VideoEngine != VIDEO_ENGINE_CME) {
   2194                     for (i = 0; (i < 50) && !(*HQVCtrl & HQV_FLIP_STATUS);
   2195                          i++) {
   2196                         DBG_DD(ErrorF(" HQV wait %d %08lx\n", i, *HQVCtrl));
   2197                         *HQVCtrl |= HQV_SW_FLIP | HQV_FLIP_STATUS;
   2198                         usleep(1);
   2199                     }
   2200                 } else {
   2201                     viaWaitHQVFlip(pVia);
   2202                 }
   2203 
   2204                 DBG_DD(ErrorF(" Wait flips6"));
   2205             }
   2206 
   2207             if (videoFlag & VIDEO_1_INUSE) {
   2208                 VIASETREG(V1_CONTROL, vidCtl);
   2209                 VIASETREG(V_COMPOSE_MODE, compose | V1_COMMAND_FIRE);
   2210                 if (pVia->swov.gdwUseExtendedFIFO) {
   2211                     /* Set Display FIFO */
   2212                     DBG_DD(ErrorF(" Wait flips7"));
   2213                     viaWaitVBI(pVia);
   2214                     DBG_DD(ErrorF(" Wait flips 8"));
   2215                     hwp->writeSeq(hwp, 0x17, 0x2F);
   2216                     ViaSeqMask(hwp, 0x16, 0x14, 0x1F);
   2217                     hwp->writeSeq(hwp, 0x18, 0x56);
   2218                     DBG_DD(ErrorF(" Wait flips 9"));
   2219                 }
   2220             } else {
   2221                 DBG_DD(ErrorF(" Wait flips 10"));
   2222                 VIASETREG(V3_CONTROL, vidCtl);
   2223                 VIASETREG(V_COMPOSE_MODE, compose | V3_COMMAND_FIRE);
   2224             }
   2225             DBG_DD(ErrorF(" Done flips"));
   2226         } else {
   2227             DBG_DD(ErrorF("    Normal called\n"));
   2228             SaveVideoRegister(pVia, HQV_CONTROL + proReg,
   2229                               hqvCtl | HQV_FLIP_STATUS);
   2230             SetVideoControl(pVia, videoFlag, vidCtl);
   2231             FireVideoCommand(pVia, videoFlag, compose);
   2232             viaWaitHQVDone(pVia);
   2233             FlushVidRegBuffer(pVia);
   2234         }
   2235     } else {
   2236         SetVideoControl(pVia, videoFlag, vidCtl);
   2237         FireVideoCommand(pVia, videoFlag, compose);
   2238         viaWaitHQVDone(pVia);
   2239         FlushVidRegBuffer(pVia);
   2240     }
   2241     pVia->swov.SWVideo_ON = TRUE;
   2242 
   2243     DBG_DD(ErrorF(" Done Upd_Video"));
   2244 
   2245     return TRUE;
   2246 
   2247 }  /* Upd_Video */
   2248 
   2249 /*
   2250  *  VIAVidUpdateOverlay()
   2251  *  Parameters:   src rectangle, dst rectangle, colorkey...
   2252  *  Return value: unsigned long of state
   2253  *  Note: updates the overlay image parameter.
   2254  */
   2255 Bool
   2256 VIAVidUpdateOverlay(xf86CrtcPtr crtc, LPDDUPDATEOVERLAY pUpdate)
   2257 {
   2258     ScrnInfoPtr pScrn = crtc->scrn;
   2259     VIAPtr pVia = VIAPTR(pScrn);
   2260     OVERLAYRECORD *ovlV1 = &pVia->swov.overlayRecordV1;
   2261 
   2262     unsigned long flags = pUpdate->dwFlags;
   2263     unsigned long videoFlag = 0;
   2264     unsigned long startAddr = 0;
   2265     unsigned long deinterlaceMode = 0;
   2266 
   2267     unsigned long haveColorKey = 0, haveChromaKey = 0;
   2268     unsigned long colorKeyLow = 0, colorKeyHigh = 0;
   2269     unsigned long chromaKeyLow = 0, chromaKeyHigh = 0;
   2270 
   2271     unsigned long scrnWidth, scrnHeight;
   2272     int dstTop, dstBottom, dstLeft, dstRight;
   2273     int panDX, panDY;               /* Panning delta */
   2274 
   2275     unsigned long proReg = 0;
   2276 
   2277     panDX = pVia->swov.panning_x;
   2278     panDY = pVia->swov.panning_y;
   2279     pVia->swov.oldPanningX = pVia->swov.panning_x;
   2280     pVia->swov.oldPanningY = pVia->swov.panning_y;
   2281 
   2282     pUpdate->DstLeft -= panDX;
   2283     pUpdate->DstTop -= panDY;
   2284     pUpdate->DstRight -= panDX;
   2285     pUpdate->DstBottom -= panDY;
   2286 
   2287     DBG_DD(ErrorF("Raw rSrc  X (%ld,%ld) Y (%ld,%ld)\n",
   2288                   pUpdate->SrcLeft, pUpdate->SrcRight,
   2289                   pUpdate->SrcTop, pUpdate->SrcBottom));
   2290     DBG_DD(ErrorF("Raw rDest  X (%ld,%ld) Y (%ld,%ld)\n",
   2291                   pUpdate->DstLeft, pUpdate->DstRight,
   2292                   pUpdate->DstTop, pUpdate->DstBottom));
   2293 
   2294     if ((pVia->swov.SrcFourCC == FOURCC_YUY2) ||
   2295         (pVia->swov.SrcFourCC == FOURCC_RV15) ||
   2296         (pVia->swov.SrcFourCC == FOURCC_RV16) ||
   2297         (pVia->swov.SrcFourCC == FOURCC_RV32) ||
   2298         (pVia->swov.SrcFourCC == FOURCC_YV12) ||
   2299         (pVia->swov.SrcFourCC == FOURCC_I420) ||
   2300         (pVia->swov.SrcFourCC == FOURCC_XVMC)) {
   2301         videoFlag = pVia->swov.gdwVideoFlagSW;
   2302     }
   2303 
   2304     if (pVia->ChipId == PCI_CHIP_VT3259 && !(videoFlag & VIDEO_1_INUSE))
   2305         proReg = PRO_HQV1_OFFSET;
   2306 
   2307     flags |= DDOVER_INTERLEAVED;
   2308 
   2309     /* Disable destination color keying if the alpha window is in use. */
   2310     if (pVia->swov.gdwAlphaEnabled)
   2311         flags &= ~DDOVER_KEYDEST;
   2312 
   2313     ResetVidRegBuffer(pVia);
   2314 
   2315     /* For SW decode HW overlay use */
   2316     startAddr = VIAGETREG(HQV_SRC_STARTADDR_Y + proReg);
   2317 
   2318     if (flags & DDOVER_KEYDEST) {
   2319         haveColorKey = 1;
   2320         colorKeyLow = pUpdate->dwColorSpaceLowValue;
   2321     }
   2322 
   2323     if (flags & DDOVER_INTERLEAVED)
   2324         deinterlaceMode |= DDOVER_INTERLEAVED;
   2325 
   2326     if (flags & DDOVER_BOB)
   2327         deinterlaceMode |= DDOVER_BOB;
   2328 
   2329     if ((pVia->ChipId == PCI_CHIP_CLE3122)
   2330         && (pScrn->currentMode->HDisplay > 1024)) {
   2331         DBG_DD(ErrorF("UseExtendedFIFO\n"));
   2332         pVia->swov.gdwUseExtendedFIFO = 1;
   2333     } else
   2334         pVia->swov.gdwUseExtendedFIFO = 0;
   2335 
   2336     /* Figure out actual rSrc rectangle */
   2337 
   2338     dstLeft = pUpdate->DstLeft;
   2339     dstTop = pUpdate->DstTop;
   2340     dstRight = pUpdate->DstRight;
   2341     dstBottom = pUpdate->DstBottom;
   2342 
   2343     scrnWidth = pScrn->currentMode->HDisplay;
   2344     scrnHeight = pScrn->currentMode->VDisplay;
   2345 
   2346     if (dstLeft < 0) {
   2347         pUpdate->SrcLeft = ((((-dstLeft) * ovlV1->dwV1OriWidth) +
   2348                              ((dstRight - dstLeft) >> 1))
   2349                             / (dstRight - dstLeft));
   2350     }
   2351     if (dstRight > scrnWidth) {
   2352         pUpdate->SrcRight = ((((scrnWidth - dstLeft) * ovlV1->dwV1OriWidth) +
   2353                               ((dstRight - dstLeft) >> 1))
   2354                              / (dstRight - dstLeft));
   2355     }
   2356     if (dstTop < 0) {
   2357         pUpdate->SrcTop = ((((-dstTop) * ovlV1->dwV1OriHeight) +
   2358                             ((dstBottom - dstTop) >> 1))
   2359                            / (dstBottom - dstTop));
   2360     }
   2361     if (dstBottom > scrnHeight) {
   2362         pUpdate->SrcBottom = ((((scrnHeight - dstTop) * ovlV1->dwV1OriHeight) +
   2363                                ((dstBottom - dstTop) >> 1))
   2364                               / (dstBottom - dstTop));
   2365     }
   2366 
   2367     /* Save modified src & original dest rectangle parameters */
   2368 
   2369     if ((pVia->swov.SrcFourCC == FOURCC_YUY2) ||
   2370         (pVia->swov.SrcFourCC == FOURCC_RV15) ||
   2371         (pVia->swov.SrcFourCC == FOURCC_RV16) ||
   2372         (pVia->swov.SrcFourCC == FOURCC_RV32) ||
   2373         (pVia->swov.SrcFourCC == FOURCC_YV12) ||
   2374         (pVia->swov.SrcFourCC == FOURCC_I420) ||
   2375         (pVia->swov.SrcFourCC == FOURCC_XVMC)) {
   2376         pVia->swov.SWDevice.gdwSWDstLeft = pUpdate->DstLeft + panDX;
   2377         pVia->swov.SWDevice.gdwSWDstTop = pUpdate->DstTop + panDY;
   2378         pVia->swov.SWDevice.gdwSWDstWidth =
   2379                 pUpdate->DstRight - pUpdate->DstLeft;
   2380         pVia->swov.SWDevice.gdwSWDstHeight =
   2381                 pUpdate->DstBottom - pUpdate->DstTop;
   2382 
   2383         pVia->swov.SWDevice.gdwSWSrcWidth = ovlV1->dwV1SrcWidth =
   2384                 pUpdate->SrcRight - pUpdate->SrcLeft;
   2385         pVia->swov.SWDevice.gdwSWSrcHeight = ovlV1->dwV1SrcHeight =
   2386                 pUpdate->SrcBottom - pUpdate->SrcTop;
   2387     }
   2388 
   2389     ovlV1->dwV1SrcLeft = pUpdate->SrcLeft;
   2390     ovlV1->dwV1SrcRight = pUpdate->SrcRight;
   2391     ovlV1->dwV1SrcTop = pUpdate->SrcTop;
   2392     ovlV1->dwV1SrcBot = pUpdate->SrcBottom;
   2393 
   2394     /* Figure out actual rDest rectangle */
   2395 
   2396     pUpdate->DstLeft = (dstLeft < 0) ? 0 : dstLeft;
   2397     pUpdate->DstTop = (dstTop < 0) ? 0 : dstTop;
   2398     if (pUpdate->DstTop >= scrnHeight)
   2399         pUpdate->DstTop = scrnHeight - 1;
   2400     pUpdate->DstRight = (dstRight > scrnWidth) ? scrnWidth : dstRight;
   2401     pUpdate->DstBottom = (dstBottom > scrnHeight) ? scrnHeight : dstBottom;
   2402 
   2403     /* Update the overlay */
   2404 
   2405     if (!Upd_Video(crtc, videoFlag, startAddr, pUpdate,
   2406                    pVia->swov.SWDevice.dwPitch, ovlV1->dwV1OriWidth,
   2407                    ovlV1->dwV1OriHeight, deinterlaceMode, haveColorKey,
   2408                    haveChromaKey, colorKeyLow, colorKeyHigh, chromaKeyLow,
   2409                    chromaKeyHigh))
   2410         return FALSE;
   2411 
   2412     pVia->swov.SWVideo_ON = FALSE;
   2413 
   2414     return TRUE;
   2415 
   2416 }  /* VIAVidUpdateOverlay */
   2417 
   2418 /*
   2419  *
   2420  */
   2421 void
   2422 ViaOverlayHide(ScrnInfoPtr pScrn)
   2423 {
   2424     VIAPtr pVia = VIAPTR(pScrn);
   2425     vgaHWPtr hwp = VGAHWPTR(pScrn);
   2426     CARD32 videoFlag = 0;
   2427     unsigned long proReg = 0;
   2428 
   2429     if ((pVia->swov.SrcFourCC == FOURCC_YUY2) ||
   2430         (pVia->swov.SrcFourCC == FOURCC_RV15) ||
   2431         (pVia->swov.SrcFourCC == FOURCC_RV16) ||
   2432         (pVia->swov.SrcFourCC == FOURCC_RV32) ||
   2433         (pVia->swov.SrcFourCC == FOURCC_YV12) ||
   2434         (pVia->swov.SrcFourCC == FOURCC_I420) ||
   2435         (pVia->swov.SrcFourCC == FOURCC_XVMC))
   2436         videoFlag = pVia->swov.gdwVideoFlagSW;
   2437 
   2438     if (pVia->ChipId == PCI_CHIP_VT3259 && !(videoFlag & VIDEO_1_INUSE))
   2439         proReg = PRO_HQV1_OFFSET;
   2440 
   2441     ResetVidRegBuffer(pVia);
   2442 
   2443     if (pVia->HWDiff.dwHQVDisablePatch)
   2444         ViaSeqMask(hwp, 0x2E, 0x00, 0x10);
   2445 
   2446     SaveVideoRegister(pVia, V_FIFO_CONTROL, V1_FIFO_PRETHRESHOLD12 |
   2447                       V1_FIFO_THRESHOLD8 | V1_FIFO_DEPTH16);
   2448     SaveVideoRegister(pVia, ALPHA_V3_FIFO_CONTROL,
   2449                       ALPHA_FIFO_THRESHOLD4 | ALPHA_FIFO_DEPTH8 |
   2450                       V3_FIFO_THRESHOLD24 | V3_FIFO_DEPTH32);
   2451 
   2452     if (videoFlag & VIDEO_HQV_INUSE)
   2453         SaveVideoRegister(pVia, HQV_CONTROL + proReg,
   2454                           VIAGETREG(HQV_CONTROL + proReg) & ~HQV_ENABLE);
   2455 
   2456     if (videoFlag & VIDEO_1_INUSE)
   2457         SaveVideoRegister(pVia, V1_CONTROL, VIAGETREG(V1_CONTROL) & ~V1_ENABLE);
   2458     else
   2459         SaveVideoRegister(pVia, V3_CONTROL, VIAGETREG(V3_CONTROL) & ~V3_ENABLE);
   2460 
   2461     FireVideoCommand(pVia, videoFlag, VIAGETREG(V_COMPOSE_MODE));
   2462     FlushVidRegBuffer(pVia);
   2463 
   2464     if (pVia->HWDiff.dwHQVDisablePatch)
   2465         ViaSeqMask(hwp, 0x2E, 0x10, 0x10);
   2466 
   2467     pVia->swov.SWVideo_ON = FALSE;
   2468     pVia->VideoStatus &= ~VIDEO_SWOV_ON;
   2469 }
   2470