Home | History | Annotate | Line # | Download | only in src
      1 /*
      2  * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
      3  * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
      4  *
      5  * Permission is hereby granted, free of charge, to any person obtaining a
      6  * copy of this software and associated documentation files (the "Software"),
      7  * to deal in the Software without restriction, including without limitation
      8  * the rights to use, copy, modify, merge, publish, distribute, sub license,
      9  * and/or sell copies of the Software, and to permit persons to whom the
     10  * Software is furnished to do so, subject to the following conditions:
     11  *
     12  * The above copyright notice and this permission notice (including the
     13  * next paragraph) shall be included in all copies or substantial portions
     14  * of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
     19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     22  * DEALINGS IN THE SOFTWARE.
     23  */
     24 
     25 /*
     26  * I N C L U D E S
     27  */
     28 
     29 #ifdef HAVE_CONFIG_H
     30 #include "config.h"
     31 #endif
     32 
     33 #include "xf86.h"
     34 #include "xf86_OSproc.h"
     35 
     36 #if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
     37 #include "xf86Resources.h"
     38 #endif
     39 
     40 #include "compiler.h"
     41 #include "xf86Pci.h"
     42 #include "regionstr.h"
     43 #include "via_driver.h"
     44 
     45 #include "xf86xv.h"
     46 #include <X11/extensions/Xv.h>
     47 #include "dixstruct.h"
     48 #include "via_xvpriv.h"
     49 #include "fourcc.h"
     50 
     51 /*
     52  * D E F I N E
     53  */
     54 #define OFF_DELAY       200           /* milliseconds */
     55 #define FREE_DELAY      60000
     56 #define PARAMSIZE       1024
     57 #define SLICESIZE       65536
     58 #define OFF_TIMER       0x01
     59 #define FREE_TIMER      0x02
     60 #define TIMER_MASK      (OFF_TIMER | FREE_TIMER)
     61 #define VIA_MAX_XVIMAGE_X 1920
     62 #define VIA_MAX_XVIMAGE_Y 1200
     63 
     64 #define LOW_BAND 0x0CB0
     65 #define MID_BAND 0x1f10
     66 
     67 #define  XV_IMAGE          0
     68 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
     69 #ifndef XvExtension
     70 void
     71 viaInitVideo(ScreenPtr pScreen)
     72 {
     73 }
     74 
     75 void
     76 viaExitVideo(ScrnInfoPtr pScrn)
     77 {
     78 }
     79 void
     80 viaSaveVideo(ScrnInfoPtr pScrn)
     81 {
     82 }
     83 void
     84 viaRestoreVideo(ScrnInfoPtr pScrn)
     85 {
     86 }
     87 void
     88 VIAVidAdjustFrame(ScrnInfoPtr pScrn, int x, int y)
     89 {
     90 }
     91 #else
     92 
     93 static vidCopyFunc viaFastVidCpy = NULL;
     94 
     95 /*
     96  *  F U N C T I O N   D E C L A R A T I O N
     97  */
     98 static unsigned viaSetupAdaptors(ScreenPtr pScreen,
     99     XF86VideoAdaptorPtr ** adaptors);
    100 static void viaStopVideo(ScrnInfoPtr, pointer, Bool);
    101 static void viaQueryBestSize(ScrnInfoPtr, Bool,
    102     short, short, short, short, unsigned int *, unsigned int *, pointer);
    103 static int viaQueryImageAttributes(ScrnInfoPtr,
    104     int, unsigned short *, unsigned short *, int *, int *);
    105 static int viaGetPortAttribute(ScrnInfoPtr, Atom, INT32 *, pointer);
    106 static int viaSetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
    107 static int viaPutImage(ScrnInfoPtr, short, short, short, short, short, short,
    108     short, short, int, unsigned char *, short, short, Bool,
    109     RegionPtr, pointer, DrawablePtr);
    110 static void UVBlit(unsigned char *dest,
    111     const unsigned char *uBuffer,
    112     const unsigned char *vBuffer,
    113     unsigned width, unsigned srcPitch, unsigned dstPitch, unsigned lines);
    114 static void nv12Blit(unsigned char *nv12Chroma,
    115     const unsigned char *uBuffer,
    116     const unsigned char *vBuffer,
    117     unsigned width, unsigned srcPitch, unsigned dstPitch, unsigned lines);
    118 
    119 static Atom xvBrightness, xvContrast, xvColorKey, xvHue, xvSaturation,
    120     xvAutoPaint;
    121 
    122 /*
    123  *  S T R U C T S
    124  */
    125 /* client libraries expect an encoding */
    126 static XF86VideoEncodingRec DummyEncoding[1] = {
    127     {XV_IMAGE, "XV_IMAGE", VIA_MAX_XVIMAGE_X, VIA_MAX_XVIMAGE_Y, {1, 1}},
    128 };
    129 
    130 #define NUM_FORMATS_G 9
    131 
    132 static XF86VideoFormatRec FormatsG[NUM_FORMATS_G] = {
    133     {8, TrueColor},               /* Dithered */
    134     {8, PseudoColor},               /* Using .. */
    135     {8, StaticColor},
    136     {8, GrayScale},
    137     {8, StaticGray},               /* .. TexelLUT */
    138     {16, TrueColor},
    139     {24, TrueColor},
    140     {16, DirectColor},
    141     {24, DirectColor}
    142 };
    143 
    144 #define NUM_ATTRIBUTES_G 6
    145 
    146 static XF86AttributeRec AttributesG[NUM_ATTRIBUTES_G] = {
    147     {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
    148     {XvSettable | XvGettable, 0, 10000, "XV_BRIGHTNESS"},
    149     {XvSettable | XvGettable, 0, 20000, "XV_CONTRAST"},
    150     {XvSettable | XvGettable, 0, 20000, "XV_SATURATION"},
    151     {XvSettable | XvGettable, -180, 180, "XV_HUE"},
    152     {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"}
    153 };
    154 
    155 #define NUM_IMAGES_G 7
    156 
    157 static XF86ImageRec ImagesG[NUM_IMAGES_G] = {
    158     XVIMAGE_YUY2,
    159     XVIMAGE_YV12,
    160     XVIMAGE_I420,
    161     {
    162         /*
    163          * Below, a dummy picture type that is used in XvPutImage only to do
    164          * an overlay update. Introduced for the XvMC client lib.
    165          * Defined to have a zero data size.
    166          */
    167 
    168         FOURCC_XVMC,
    169         XvYUV,
    170         LSBFirst,
    171         {   'V', 'I', 'A', 0x00,
    172             0x00, 0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0xAA, 0x00,
    173             0x38, 0x9B, 0x71},
    174         12,
    175         XvPlanar,
    176         1,
    177         0, 0, 0, 0,
    178         8, 8, 8,
    179         1, 2, 2,
    180         1, 2, 2,
    181         {   'Y', 'V', 'U',
    182             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    183             0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    184         XvTopToBottom},
    185     { /* RGB 555 */
    186         FOURCC_RV15,
    187         XvRGB,
    188         LSBFirst,
    189         {   'R', 'V', '1', '5',
    190             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    191             0x00, 0x00, 0x00},
    192         16,
    193         XvPacked,
    194         1,
    195         15, 0x7C00, 0x03E0, 0x001F,
    196         0, 0, 0,
    197         0, 0, 0,
    198         0, 0, 0,
    199         {   'R', 'V', 'B', 0,
    200             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    201             0, 0, 0, 0, 0, 0, 0, 0, 0},
    202         XvTopToBottom},
    203     { /* RGB 565 */
    204         FOURCC_RV16,
    205         XvRGB,
    206         LSBFirst,
    207         {   'R', 'V', '1', '6',
    208             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    209             0x00, 0x00, 0x00},
    210         16,
    211         XvPacked,
    212         1,
    213         16, 0xF800, 0x07E0, 0x001F,
    214         0, 0, 0,
    215         0, 0, 0,
    216         0, 0, 0,
    217         {   'R', 'V', 'B', 0,
    218             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    219             0, 0, 0, 0, 0, 0, 0, 0, 0},
    220         XvTopToBottom},
    221     { /* RGB 888 */
    222         FOURCC_RV32,
    223         XvRGB,
    224         LSBFirst,
    225         {   'R', 'V', '3', '2',
    226             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    227             0x00, 0x00, 0x00},
    228         32,
    229         XvPacked,
    230         1,
    231         24, 0xff0000, 0x00ff00, 0x0000ff,
    232         0, 0, 0,
    233         0, 0, 0,
    234         0, 0, 0,
    235         {   'R', 'V', 'B', 0,
    236             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    237             0, 0, 0, 0, 0, 0, 0, 0, 0},
    238         XvTopToBottom}
    239 
    240 };
    241 
    242 static char *XvAdaptorName[XV_ADAPT_NUM] = {
    243     "XV_SWOV"
    244 };
    245 
    246 static XF86VideoAdaptorPtr viaAdaptPtr[XV_ADAPT_NUM];
    247 static XF86VideoAdaptorPtr *allAdaptors;
    248 static unsigned numAdaptPort[XV_ADAPT_NUM] = { 1 };
    249 
    250 /*
    251  *  F U N C T I O N
    252  */
    253 
    254 /*
    255  *   Decide if the mode support video overlay. This depends on the bandwidth
    256  *   of the mode and the type of RAM available.
    257  */
    258 
    259 static Bool
    260 DecideOverlaySupport(xf86CrtcPtr crtc)
    261 {
    262     DisplayModePtr mode = &crtc->desiredMode;
    263     ScrnInfoPtr pScrn = crtc->scrn;
    264     VIAPtr pVia = VIAPTR(pScrn);
    265 
    266 #ifdef HAVE_DEBUG
    267     if (pVia->disableXvBWCheck)
    268         return TRUE;
    269 #endif
    270 
    271     /* Small trick here. We keep the height in 16's of lines and width in 32's
    272      * to avoid numeric overflow */
    273 
    274     if (pVia->ChipId != PCI_CHIP_VT3205 &&
    275         pVia->ChipId != PCI_CHIP_VT3204 &&
    276         pVia->ChipId != PCI_CHIP_VT3259 &&
    277         pVia->ChipId != PCI_CHIP_VT3314 &&
    278         pVia->ChipId != PCI_CHIP_VT3327 &&
    279         pVia->ChipId != PCI_CHIP_VT3336 &&
    280         pVia->ChipId != PCI_CHIP_VT3409 &&
    281         pVia->ChipId != PCI_CHIP_VT3410 &&
    282         pVia->ChipId != PCI_CHIP_VT3364 &&
    283         pVia->ChipId != PCI_CHIP_VT3324 &&
    284         pVia->ChipId != PCI_CHIP_VT3353) {
    285         CARD32 bandwidth = (mode->HDisplay >> 4) * (mode->VDisplay >> 5) *
    286                             pScrn->bitsPerPixel * mode->VRefresh;
    287 
    288         switch (pVia->MemClk) {
    289         case VIA_MEM_SDR100:           /* No overlay without DDR */
    290         case VIA_MEM_SDR133:
    291             return FALSE;
    292         case VIA_MEM_DDR200:
    293             /* Basic limit for DDR200 is about this */
    294             if (bandwidth > 1800000)
    295                 return FALSE;
    296             /* But we have constraints at higher than 800x600 */
    297             if (mode->HDisplay > 800) {
    298                 if (pScrn->bitsPerPixel != 8)
    299                     return FALSE;
    300                 if (mode->VDisplay > 768)
    301                     return FALSE;
    302                 if (mode->VRefresh > 60)
    303                     return FALSE;
    304             }
    305             return TRUE;
    306         case 0:               /*      FIXME: Why does my CLE266 report 0? */
    307         case VIA_MEM_DDR266:
    308             if (bandwidth > 7901250)
    309                 return FALSE;
    310             return TRUE;
    311         }
    312         return FALSE;
    313 
    314     } else {
    315         unsigned width, height, refresh, dClock;
    316         float mClock, memEfficiency, needBandWidth, totalBandWidth;
    317 
    318         switch (pVia->MemClk) {
    319             case VIA_MEM_SDR100:
    320                 mClock = 50;           /*HW base on 128 bit */
    321                 memEfficiency = (float)SINGLE_3205_100;
    322                 break;
    323             case VIA_MEM_SDR133:
    324                 mClock = 66.5;
    325                 memEfficiency = (float)SINGLE_3205_100;
    326                 break;
    327             case VIA_MEM_DDR200:
    328                 mClock = 100;
    329                 memEfficiency = (float)SINGLE_3205_100;
    330                 break;
    331             case VIA_MEM_DDR266:
    332                 mClock = 133;
    333                 memEfficiency = (float)SINGLE_3205_133;
    334                 break;
    335             case VIA_MEM_DDR333:
    336                 mClock = 166;
    337                 memEfficiency = (float)SINGLE_3205_133;
    338                 break;
    339             case VIA_MEM_DDR400:
    340                 mClock = 200;
    341                 memEfficiency = (float)SINGLE_3205_133;
    342                 break;
    343             case VIA_MEM_DDR533:
    344                 mClock = 266;
    345                 memEfficiency = (float)SINGLE_3205_133;
    346                 break;
    347             case VIA_MEM_DDR667:
    348                 mClock = 333;
    349                 memEfficiency = (float)SINGLE_3205_133;
    350                 break;
    351             case VIA_MEM_DDR800:
    352                 mClock = 400;
    353                 memEfficiency = (float)SINGLE_3205_133;
    354                 break;
    355             case VIA_MEM_DDR1066:
    356                 mClock = 533;
    357                 memEfficiency = (float)SINGLE_3205_133;
    358                 break;
    359             default:
    360                 ErrorF("Unknown DRAM Type!\n");
    361                 mClock = 166;
    362                 memEfficiency = (float)SINGLE_3205_133;
    363                 break;
    364         }
    365 
    366         width = mode->HDisplay;
    367         height = mode->VDisplay;
    368         refresh = mode->VRefresh;
    369 
    370         if (refresh==0) {
    371             refresh=60;
    372             ErrorF("Unable to fetch vertical refresh value, needed for bandwidth calculation.\n");
    373         }
    374 
    375         /*
    376          * Approximative, VERY conservative formula in some cases.
    377          * This formula and the one below are derived analyzing the
    378          * tables present in VIA's own drivers. They may reject the over-
    379          * lay in some cases where VIA's driver don't.
    380          */
    381         dClock = (width * height * refresh) / 680000;
    382         if (dClock) {
    383             needBandWidth =
    384                 (float)(((pScrn->bitsPerPixel >> 3) + VIDEO_BPP) * dClock);
    385             totalBandWidth = (float)(mClock * 16. * memEfficiency);
    386 
    387             DBG_DD(ErrorF(" via_xv.c : cBitsPerPel= %d : \n",
    388                 pScrn->bitsPerPixel));
    389             DBG_DD(ErrorF(" via_xv.c : Video_Bpp= %d : \n", VIDEO_BPP));
    390             DBG_DD(ErrorF(" via_xv.c : refresh = %d : \n", refresh));
    391             DBG_DD(ErrorF(" via_xv.c : dClock= %d : \n", dClock));
    392             DBG_DD(ErrorF(" via_xv.c : mClk= %f : \n", mClock));
    393             DBG_DD(ErrorF(" via_xv.c : memEfficiency= %f : \n",
    394                 memEfficiency));
    395             if (needBandWidth < totalBandWidth)
    396                 return TRUE;
    397             ErrorF(" via_xv.c : needBandwidth= %f : \n",
    398                 needBandWidth);
    399             ErrorF(" via_xv.c : totalBandwidth= %f : \n",
    400                 totalBandWidth);
    401         }
    402         return FALSE;
    403     }
    404     return FALSE;
    405 }
    406 
    407 static const char *viaXvErrMsg[xve_numerr] = { "No Error.",
    408     "Bandwidth is insufficient. Check bios memory settings.",
    409     "PCI DMA blit failed. You probably encountered a bug.",
    410     "Not enough resources to complete the request. Probably out of memory.",
    411     "General Error. I wish I could be more specific.",
    412     "Wrong adaptor used. Try another port number."
    413 };
    414 
    415 static void
    416 viaXvError(ScrnInfoPtr pScrn, viaPortPrivPtr pPriv, XvError error)
    417 {
    418     if (error == xve_none) {
    419         pPriv->xvErr = xve_none;
    420         return;
    421     }
    422     if (error == pPriv->xvErr) {
    423         return;
    424     }
    425     pPriv->xvErr = error;
    426     xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[Xv] Port %d: %s\n",
    427             pPriv->xv_portnum, viaXvErrMsg[error]);
    428 }
    429 
    430 static void
    431 viaResetVideo(ScrnInfoPtr pScrn)
    432 {
    433     VIAPtr pVia = VIAPTR(pScrn);
    434     vmmtr viaVidEng = (vmmtr) (pVia->MapBase + 0x200);
    435 
    436     DBG_DD(ErrorF(" via_xv.c : viaResetVideo: \n"));
    437 
    438     viaVidEng->video1_ctl = 0;
    439     viaVidEng->video3_ctl = 0;
    440     viaVidEng->compose = V1_COMMAND_FIRE;
    441     viaVidEng->compose = V3_COMMAND_FIRE;
    442     viaVidEng->color_key = 0x821;
    443     viaVidEng->snd_color_key = 0x821;
    444 }
    445 
    446 void
    447 viaSaveVideo(ScrnInfoPtr pScrn)
    448 {
    449     VIAPtr pVia = VIAPTR(pScrn);
    450     vmmtr viaVidEng = (vmmtr) (pVia->MapBase + 0x200);
    451 
    452     DBG_DD(ErrorF(" via_xv.c : viaSaveVideo : \n"));
    453     /* Save video registers */
    454     memcpy(pVia->VideoRegs, (void*)viaVidEng, sizeof(video_via_regs));
    455 
    456     pVia->dwV1 = ((vmmtr) viaVidEng)->video1_ctl;
    457     pVia->dwV3 = ((vmmtr) viaVidEng)->video3_ctl;
    458     viaVidEng->video1_ctl = 0;
    459     viaVidEng->video3_ctl = 0;
    460     viaVidEng->compose = V1_COMMAND_FIRE;
    461     viaVidEng->compose = V3_COMMAND_FIRE;
    462 }
    463 
    464 void
    465 viaRestoreVideo(ScrnInfoPtr pScrn)
    466 {
    467     VIAPtr pVia = VIAPTR(pScrn);
    468     vmmtr viaVidEng = (vmmtr) (pVia->MapBase + 0x200);
    469     video_via_regs  *localVidEng = pVia->VideoRegs;
    470 
    471     DBG_DD(ErrorF(" via_xv.c : viaRestoreVideo : \n"));
    472 
    473     /* Restore video registers */
    474     /* flush restored video engines' setting to MapBase */
    475     viaVidEng->alphawin_hvstart = localVidEng->alphawin_hvstart;
    476     viaVidEng->alphawin_size   = localVidEng->alphawin_size;
    477     viaVidEng->alphawin_ctl    = localVidEng->alphawin_ctl;
    478     viaVidEng->alphafb_stride  = localVidEng->alphafb_stride;
    479     viaVidEng->color_key       = localVidEng->color_key;
    480     viaVidEng->alphafb_addr    = localVidEng->alphafb_addr;
    481     viaVidEng->chroma_low      = localVidEng->chroma_low;
    482     viaVidEng->chroma_up       = localVidEng->chroma_up;
    483     viaVidEng->interruptflag   = localVidEng->interruptflag;
    484 
    485     if (pVia->ChipId != PCI_CHIP_VT3314)
    486     {
    487         /*VT3314 only has V3*/
    488         viaVidEng->video1_ctl      = localVidEng->video1_ctl;
    489         viaVidEng->video1_fetch    = localVidEng->video1_fetch;
    490         viaVidEng->video1y_addr1   = localVidEng->video1y_addr1;
    491         viaVidEng->video1_stride   = localVidEng->video1_stride;
    492         viaVidEng->video1_hvstart  = localVidEng->video1_hvstart;
    493         viaVidEng->video1_size     = localVidEng->video1_size;
    494         viaVidEng->video1y_addr2   = localVidEng->video1y_addr2;
    495         viaVidEng->video1_zoom     = localVidEng->video1_zoom;
    496         viaVidEng->video1_mictl    = localVidEng->video1_mictl;
    497         viaVidEng->video1y_addr0   = localVidEng->video1y_addr0;
    498         viaVidEng->video1_fifo     = localVidEng->video1_fifo;
    499         viaVidEng->video1y_addr3   = localVidEng->video1y_addr3;
    500         viaVidEng->v1_source_w_h   = localVidEng->v1_source_w_h;
    501         viaVidEng->video1_CSC1     = localVidEng->video1_CSC1;
    502         viaVidEng->video1_CSC2     = localVidEng->video1_CSC2;
    503 
    504         /* Fix cursor garbage after suspend for VX855 and VX900 (#405) */
    505         /* 0x2E4 T Signature Data Result 1 */
    506         viaVidEng->video1u_addr1         = localVidEng->video1u_addr1;
    507         /* 0x2E8 HI for Primary Display FIFO Control Signal */
    508         viaVidEng->video1u_addr2         = localVidEng->video1u_addr2;
    509         /* 0x2EC HI for Primary Display FIFO Transparent color */
    510         viaVidEng->video1u_addr3         = localVidEng->video1u_addr3;
    511         /* 0x2F0 HI for Primary Display Control Signal */
    512         viaVidEng->video1v_addr0         = localVidEng->video1v_addr0;
    513         /* 0x2F4 HI for Primary Display Frame Buffer Starting Address */
    514         viaVidEng->video1v_addr1         = localVidEng->video1v_addr1;
    515         /* 0x2F8 HI for Primary Display Horizontal and Vertical Start */
    516         viaVidEng->video1v_addr2         = localVidEng->video1v_addr2;
    517         /* 0x2FC HI for Primary Display Center Offset */
    518         viaVidEng->video1v_addr3         = localVidEng->video1v_addr3;
    519     }
    520     viaVidEng->snd_color_key   = localVidEng->snd_color_key;
    521     viaVidEng->v3alpha_prefifo = localVidEng->v3alpha_prefifo;
    522     viaVidEng->v3alpha_fifo    = localVidEng->v3alpha_fifo;
    523     viaVidEng->video3_CSC2     = localVidEng->video3_CSC2;
    524     viaVidEng->video3_CSC2     = localVidEng->video3_CSC2;
    525     viaVidEng->v3_source_width = localVidEng->v3_source_width;
    526     viaVidEng->video3_ctl      = localVidEng->video3_ctl;
    527     viaVidEng->video3_addr0    = localVidEng->video3_addr0;
    528     viaVidEng->video3_addr1    = localVidEng->video3_addr1;
    529     viaVidEng->video3_stride   = localVidEng->video3_stride;
    530     viaVidEng->video3_hvstart  = localVidEng->video3_hvstart;
    531     viaVidEng->video3_size     = localVidEng->video3_size;
    532     viaVidEng->v3alpha_fetch   = localVidEng->v3alpha_fetch;
    533     viaVidEng->video3_zoom     = localVidEng->video3_zoom;
    534     viaVidEng->video3_mictl    = localVidEng->video3_mictl;
    535     viaVidEng->video3_CSC1     = localVidEng->video3_CSC1;
    536     viaVidEng->video3_CSC2     = localVidEng->video3_CSC2;
    537     viaVidEng->compose         = localVidEng->compose;
    538     viaVidEng->video3_ctl      = pVia->dwV3;
    539 
    540     if (pVia->ChipId != PCI_CHIP_VT3314) {
    541         viaVidEng->video1_ctl = pVia->dwV1;
    542         viaVidEng->compose = V1_COMMAND_FIRE;
    543     }
    544     viaVidEng->compose = V3_COMMAND_FIRE;
    545 }
    546 
    547 void
    548 viaExitVideo(ScrnInfoPtr pScrn)
    549 {
    550     VIAPtr pVia = VIAPTR(pScrn);
    551     vmmtr viaVidEng = (vmmtr) (pVia->MapBase + 0x200);
    552     XF86VideoAdaptorPtr curAdapt;
    553     int i, j, numPorts;
    554 
    555     DBG_DD(ErrorF(" via_xv.c : viaExitVideo : \n"));
    556 
    557 #ifdef HAVE_DRI
    558     ViaCleanupXVMC(pScrn, viaAdaptPtr, XV_ADAPT_NUM);
    559 #endif
    560 
    561     viaVidEng->video1_ctl = 0;
    562     viaVidEng->video3_ctl = 0;
    563     viaVidEng->compose = V1_COMMAND_FIRE;
    564     viaVidEng->compose = V3_COMMAND_FIRE;
    565 
    566     /*
    567      * Free all adaptor info allocated in viaInitVideo.
    568      */
    569 
    570     for (i = 0; i < XV_ADAPT_NUM; ++i) {
    571         curAdapt = viaAdaptPtr[i];
    572         if (curAdapt) {
    573             if (curAdapt->pPortPrivates) {
    574                 if (curAdapt->pPortPrivates->ptr) {
    575                     numPorts = numAdaptPort[i];
    576                     for (j = 0; j < numPorts; ++j) {
    577                         viaStopVideo(pScrn,
    578                             (viaPortPrivPtr) curAdapt->pPortPrivates->ptr + j,
    579                             TRUE);
    580                     }
    581                     free(curAdapt->pPortPrivates->ptr);
    582                 }
    583                 free(curAdapt->pPortPrivates);
    584             }
    585             free(curAdapt);
    586         }
    587     }
    588     if (allAdaptors)
    589         free(allAdaptors);
    590 }
    591 
    592 void
    593 viaInitVideo(ScreenPtr pScreen)
    594 {
    595     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
    596     XF86VideoAdaptorPtr *adaptors, *newAdaptors;
    597     VIAPtr pVia = VIAPTR(pScrn);
    598     int num_adaptors, num_new;
    599 
    600     DBG_DD(ErrorF(" via_xv.c : viaInitVideo, Screen[%d]\n", pScrn->scrnIndex));
    601 
    602     allAdaptors = NULL;
    603     newAdaptors = NULL;
    604     num_new = 0;
    605 
    606     pVia->useDmaBlit = FALSE;
    607 #ifdef HAVE_DRI
    608     pVia->useDmaBlit = (pVia->directRenderingType == DRI_1) &&
    609     ((pVia->Chipset == VIA_CLE266) ||
    610         (pVia->Chipset == VIA_KM400) ||
    611         (pVia->Chipset == VIA_K8M800) ||
    612         (pVia->Chipset == VIA_PM800) ||
    613         (pVia->Chipset == VIA_P4M800PRO) ||
    614         (pVia->Chipset == VIA_K8M890) ||
    615         (pVia->Chipset == VIA_P4M900) ||
    616         (pVia->Chipset == VIA_CX700) ||
    617         (pVia->Chipset == VIA_VX800) ||
    618         (pVia->Chipset == VIA_VX855) ||
    619         (pVia->Chipset == VIA_VX900) ||
    620         (pVia->Chipset == VIA_P4M890));
    621     if ((pVia->drmVerMajor < 2) ||
    622         ((pVia->drmVerMajor == 2) && (pVia->drmVerMinor < 9)))
    623         pVia->useDmaBlit = FALSE;
    624 #endif
    625     pVia->useDmaBlit = pVia->useDmaBlit && pVia->dmaXV;
    626 
    627     if (pVia->useDmaBlit)
    628         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
    629             "[Xv] Using PCI DMA for Xv image transfer.\n");
    630 
    631     if (!viaFastVidCpy)
    632         viaFastVidCpy = viaVidCopyInit("video", pScreen);
    633 
    634     if ((pVia->Chipset == VIA_CLE266) || (pVia->Chipset == VIA_KM400) ||
    635         (pVia->Chipset == VIA_K8M800) || (pVia->Chipset == VIA_PM800) ||
    636         (pVia->Chipset == VIA_P4M800PRO) || (pVia->Chipset == VIA_K8M890) ||
    637         (pVia->Chipset == VIA_P4M900) || (pVia->Chipset == VIA_CX700) ||
    638         (pVia->Chipset == VIA_P4M890) || (pVia->Chipset == VIA_VX800) ||
    639         (pVia->Chipset == VIA_VX855 || (pVia->Chipset == VIA_VX900))) {
    640         num_new = viaSetupAdaptors(pScreen, &newAdaptors);
    641         num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
    642     } else {
    643         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
    644                 "[Xv] Unsupported Chipset. X video functionality disabled.\n");
    645         num_adaptors = 0;
    646         memset(viaAdaptPtr, 0, sizeof(viaAdaptPtr));
    647     }
    648 
    649     DBG_DD(ErrorF(" via_xv.c : num_adaptors : %d\n", num_adaptors));
    650     if (newAdaptors) {
    651         allAdaptors = malloc((num_adaptors + num_new) *
    652                 sizeof(XF86VideoAdaptorPtr *));
    653         if (allAdaptors) {
    654             if (num_adaptors)
    655                 memcpy(allAdaptors, adaptors,
    656                     num_adaptors * sizeof(XF86VideoAdaptorPtr));
    657             memcpy(allAdaptors + num_adaptors, newAdaptors,
    658                     num_new * sizeof(XF86VideoAdaptorPtr));
    659             num_adaptors += num_new;
    660         }
    661     }
    662 
    663     if (num_adaptors) {
    664         xf86XVScreenInit(pScreen, allAdaptors, num_adaptors);
    665 #ifdef HAVE_DRI
    666         ViaInitXVMC(pScreen);
    667 #endif
    668         viaSetColorSpace(pVia, 0, 0, 0, 0, TRUE);
    669         pVia->swov.panning_x = 0;
    670         pVia->swov.panning_y = 0;
    671         pVia->swov.oldPanningX = 0;
    672         pVia->swov.oldPanningY = 0;
    673     }
    674 }
    675 
    676 static unsigned
    677 viaSetupAdaptors(ScreenPtr pScreen, XF86VideoAdaptorPtr ** adaptors)
    678 {
    679     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
    680     int i, j, usedPorts, numPorts;
    681     viaPortPrivRec *viaPortPriv;
    682     DevUnion *pdevUnion;
    683 
    684     DBG_DD(ErrorF(" via_xv.c : viaSetupAdaptors (viaSetupImageVideo): \n"));
    685 
    686     xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
    687     xvContrast = MAKE_ATOM("XV_CONTRAST");
    688     xvColorKey = MAKE_ATOM("XV_COLORKEY");
    689     xvHue = MAKE_ATOM("XV_HUE");
    690     xvSaturation = MAKE_ATOM("XV_SATURATION");
    691     xvAutoPaint = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");
    692 
    693     *adaptors = NULL;
    694     usedPorts = 0;
    695 
    696     for (i = 0; i < XV_ADAPT_NUM; i++) {
    697         if (!(viaAdaptPtr[i] = xf86XVAllocateVideoAdaptorRec(pScrn)))
    698             return 0;
    699         numPorts = numAdaptPort[i];
    700 
    701         viaPortPriv =
    702             (viaPortPrivPtr) xnfcalloc(numPorts, sizeof(viaPortPrivRec));
    703         pdevUnion = (DevUnion *) xnfcalloc(numPorts, sizeof(DevUnion));
    704 
    705         if (i == XV_ADAPT_SWOV) { /* Overlay engine */
    706             viaAdaptPtr[i]->type = XvInputMask | XvWindowMask | XvImageMask |
    707             XvVideoMask | XvStillMask;
    708             viaAdaptPtr[i]->flags =
    709             VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
    710         } else {
    711             viaAdaptPtr[i]->type = XvInputMask | XvWindowMask | XvVideoMask;
    712             viaAdaptPtr[i]->flags =
    713             VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
    714         }
    715         viaAdaptPtr[i]->name = XvAdaptorName[i];
    716         viaAdaptPtr[i]->nEncodings = 1;
    717         viaAdaptPtr[i]->pEncodings = DummyEncoding;
    718         viaAdaptPtr[i]->nFormats = sizeof(FormatsG) / sizeof(FormatsG[0]);
    719         viaAdaptPtr[i]->pFormats = FormatsG;
    720 
    721         /* The adapter can handle 1 port simultaneously */
    722         viaAdaptPtr[i]->nPorts = numPorts;
    723         viaAdaptPtr[i]->pPortPrivates = pdevUnion;
    724         viaAdaptPtr[i]->pPortPrivates->ptr = (pointer) viaPortPriv;
    725         viaAdaptPtr[i]->nAttributes = NUM_ATTRIBUTES_G;
    726         viaAdaptPtr[i]->pAttributes = AttributesG;
    727 
    728         viaAdaptPtr[i]->nImages = NUM_IMAGES_G;
    729         viaAdaptPtr[i]->pImages = ImagesG;
    730         viaAdaptPtr[i]->PutVideo = NULL;
    731         viaAdaptPtr[i]->StopVideo = viaStopVideo;
    732         viaAdaptPtr[i]->QueryBestSize = viaQueryBestSize;
    733         viaAdaptPtr[i]->GetPortAttribute = viaGetPortAttribute;
    734         viaAdaptPtr[i]->SetPortAttribute = viaSetPortAttribute;
    735         viaAdaptPtr[i]->PutImage = viaPutImage;
    736         viaAdaptPtr[i]->ReputImage = NULL;
    737         viaAdaptPtr[i]->QueryImageAttributes = viaQueryImageAttributes;
    738         for (j = 0; j < numPorts; ++j) {
    739             viaPortPriv[j].dmaBounceBuffer = NULL;
    740             viaPortPriv[j].dmaBounceStride = 0;
    741             viaPortPriv[j].dmaBounceLines = 0;
    742             viaPortPriv[j].colorKey = 0x0821;
    743             viaPortPriv[j].autoPaint = TRUE;
    744             viaPortPriv[j].brightness = 5000.;
    745             viaPortPriv[j].saturation = 10000;
    746             viaPortPriv[j].contrast = 10000;
    747             viaPortPriv[j].hue = 0;
    748             viaPortPriv[j].FourCC = 0;
    749             viaPortPriv[j].xv_portnum = j + usedPorts;
    750             viaPortPriv[j].xvErr = xve_none;
    751 
    752 #ifdef X_USE_REGION_NULL
    753             REGION_NULL(pScreen, &viaPortPriv[j].clip);
    754 #else
    755             REGION_INIT(pScreen, &viaPortPriv[j].clip, NullBox, 1);
    756 #endif
    757         }
    758         usedPorts += j;
    759 
    760 #ifdef HAVE_DRI
    761         viaXvMCInitXv(pScrn, viaAdaptPtr[i]);
    762 #endif
    763 
    764     } /* End of for */
    765     viaResetVideo(pScrn);
    766     *adaptors = viaAdaptPtr;
    767     return XV_ADAPT_NUM;
    768 }
    769 
    770 static void
    771 viaStopVideo(ScrnInfoPtr pScrn, pointer data, Bool exit)
    772 {
    773     VIAPtr pVia = VIAPTR(pScrn);
    774     viaPortPrivPtr pPriv = (viaPortPrivPtr) data;
    775 
    776     DBG_DD(ErrorF(" via_xv.c : viaStopVideo: exit=%d\n", exit));
    777 
    778     REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
    779     ViaOverlayHide(pScrn);
    780     if (exit) {
    781         ViaSwovSurfaceDestroy(pScrn, pPriv);
    782         if (pPriv->dmaBounceBuffer)
    783             free(pPriv->dmaBounceBuffer);
    784         pPriv->dmaBounceBuffer = 0;
    785         pPriv->dmaBounceStride = 0;
    786         pPriv->dmaBounceLines = 0;
    787         pVia->dwFrameNum = 0;
    788         pPriv->old_drw_x = 0;
    789         pPriv->old_drw_y = 0;
    790         pPriv->old_drw_w = 0;
    791         pPriv->old_drw_h = 0;
    792     }
    793 }
    794 
    795 static int
    796 viaSetPortAttribute(ScrnInfoPtr pScrn,
    797         Atom attribute, INT32 value, pointer data)
    798 {
    799     VIAPtr pVia = VIAPTR(pScrn);
    800     vmmtr viaVidEng = (vmmtr) (pVia->MapBase + 0x200);
    801     viaPortPrivPtr pPriv = (viaPortPrivPtr) data;
    802     int attr, avalue;
    803 
    804     DBG_DD(ErrorF(" via_xv.c : viaSetPortAttribute : \n"));
    805 
    806     /* Color Key */
    807     if (attribute == xvColorKey) {
    808         DBG_DD(ErrorF("  V4L Disable  xvColorKey = %08lx\n", value));
    809 
    810         pPriv->colorKey = value;
    811         /* All assume color depth is 16 */
    812         value &= 0x00FFFFFF;
    813         viaVidEng->color_key = value;
    814         viaVidEng->snd_color_key = value;
    815         REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
    816         DBG_DD(ErrorF("  V4L Disable done  xvColorKey = %08lx\n", value));
    817 
    818     } else if (attribute == xvAutoPaint) {
    819         pPriv->autoPaint = value;
    820         DBG_DD(ErrorF("       xvAutoPaint = %08lx\n", value));
    821         /* Color Control */
    822     } else if (attribute == xvBrightness ||
    823             attribute == xvContrast ||
    824             attribute == xvSaturation || attribute == xvHue) {
    825         if (attribute == xvBrightness) {
    826             DBG_DD(ErrorF("     xvBrightness = %08ld\n", value));
    827             pPriv->brightness = value;
    828         }
    829         if (attribute == xvContrast) {
    830             DBG_DD(ErrorF("     xvContrast = %08ld\n", value));
    831             pPriv->contrast = value;
    832         }
    833         if (attribute == xvSaturation) {
    834             DBG_DD(ErrorF("     xvSaturation = %08ld\n", value));
    835             pPriv->saturation = value;
    836         }
    837         if (attribute == xvHue) {
    838             DBG_DD(ErrorF("     xvHue = %08ld\n", value));
    839             pPriv->hue = value;
    840         }
    841         viaSetColorSpace(pVia, pPriv->hue, pPriv->saturation,
    842                 pPriv->brightness, pPriv->contrast, FALSE);
    843     } else {
    844         DBG_DD(ErrorF
    845                 (" via_xv.c : viaSetPortAttribute : is not supported the attribute"));
    846         return BadMatch;
    847     }
    848 
    849     /* attr,avalue hardware processing goes here */
    850     (void)attr;
    851     (void)avalue;
    852 
    853     return Success;
    854 }
    855 
    856 static int
    857 viaGetPortAttribute(ScrnInfoPtr pScrn,
    858         Atom attribute, INT32 * value, pointer data)
    859 {
    860     viaPortPrivPtr pPriv = (viaPortPrivPtr) data;
    861 
    862     DBG_DD(ErrorF(" via_xv.c : viaGetPortAttribute : port %d %ld\n",
    863                     pPriv->xv_portnum, attribute));
    864 
    865     *value = 0;
    866     if (attribute == xvColorKey) {
    867         *value = (INT32) pPriv->colorKey;
    868         DBG_DD(ErrorF(" via_xv.c :    ColorKey 0x%lx\n", pPriv->colorKey));
    869     } else if (attribute == xvAutoPaint) {
    870         *value = (INT32) pPriv->autoPaint;
    871         DBG_DD(ErrorF("    AutoPaint = %08ld\n", *value));
    872         /* Color Control */
    873     } else if (attribute == xvBrightness ||
    874             attribute == xvContrast ||
    875             attribute == xvSaturation || attribute == xvHue) {
    876         if (attribute == xvBrightness) {
    877             *value = pPriv->brightness;
    878             DBG_DD(ErrorF("    xvBrightness = %08ld\n", *value));
    879         }
    880         if (attribute == xvContrast) {
    881             *value = pPriv->contrast;
    882             DBG_DD(ErrorF("    xvContrast = %08ld\n", *value));
    883         }
    884         if (attribute == xvSaturation) {
    885             *value = pPriv->saturation;
    886             DBG_DD(ErrorF("    xvSaturation = %08ld\n", *value));
    887         }
    888         if (attribute == xvHue) {
    889             *value = pPriv->hue;
    890             DBG_DD(ErrorF("    xvHue = %08ld\n", *value));
    891         }
    892 
    893     } else {
    894         DBG_DD(ErrorF(" via_xv.c : viaGetPortAttribute : is not supported the attribute\n"));
    895         /*return BadMatch */;
    896     }
    897     return Success;
    898 }
    899 
    900 static void
    901 viaQueryBestSize(ScrnInfoPtr pScrn,
    902     Bool motion,
    903     short vid_w, short vid_h,
    904     short drw_w, short drw_h,
    905     unsigned int *p_w, unsigned int *p_h, pointer data)
    906 {
    907     DBG_DD(ErrorF(" via_xv.c : viaQueryBestSize :\n"));
    908     *p_w = drw_w;
    909     *p_h = drw_h;
    910 
    911     if (*p_w > 2048)
    912         *p_w = 2048;
    913 }
    914 
    915 /*
    916  *  To do SW Flip
    917  */
    918 static void
    919 Flip(VIAPtr pVia, viaPortPrivPtr pPriv, int fourcc,
    920         unsigned long DisplayBufferIndex)
    921 {
    922     unsigned long proReg = 0;
    923     unsigned count = 50000;
    924 
    925     if (pVia->ChipId == PCI_CHIP_VT3259
    926         && !(pVia->swov.gdwVideoFlagSW & VIDEO_1_INUSE))
    927         proReg = PRO_HQV1_OFFSET;
    928 
    929     switch (fourcc) {
    930         case FOURCC_UYVY:
    931         case FOURCC_YUY2:
    932         case FOURCC_RV15:
    933         case FOURCC_RV16:
    934         case FOURCC_RV32:
    935             while ((VIAGETREG(HQV_CONTROL + proReg) & HQV_SW_FLIP)
    936                     && --count);
    937             VIASETREG(HQV_SRC_STARTADDR_Y + proReg,
    938                 pVia->swov.SWDevice.dwSWPhysicalAddr[DisplayBufferIndex]);
    939             VIASETREG(HQV_CONTROL + proReg, (VIAGETREG(HQV_CONTROL + proReg) & ~HQV_FLIP_ODD) | HQV_SW_FLIP | HQV_FLIP_STATUS);
    940             break;
    941         case FOURCC_YV12:
    942         case FOURCC_I420:
    943         default:
    944             while ((VIAGETREG(HQV_CONTROL + proReg) & HQV_SW_FLIP)
    945                     && --count);
    946             VIASETREG(HQV_SRC_STARTADDR_Y + proReg,
    947                 pVia->swov.SWDevice.dwSWPhysicalAddr[DisplayBufferIndex]);
    948             if (pVia->VideoEngine == VIDEO_ENGINE_CME) {
    949                 VIASETREG(HQV_SRC_STARTADDR_U + proReg,
    950                 pVia->swov.SWDevice.dwSWCrPhysicalAddr[DisplayBufferIndex]);
    951             } else {
    952                 VIASETREG(HQV_SRC_STARTADDR_U,
    953                     pVia->swov.SWDevice.dwSWCbPhysicalAddr[DisplayBufferIndex]);
    954                 VIASETREG(HQV_SRC_STARTADDR_V,
    955                     pVia->swov.SWDevice.dwSWCrPhysicalAddr[DisplayBufferIndex]);
    956             }
    957             VIASETREG(HQV_CONTROL + proReg, (VIAGETREG(HQV_CONTROL + proReg) & ~HQV_FLIP_ODD) | HQV_SW_FLIP | HQV_FLIP_STATUS);
    958 	    break;
    959     }
    960 }
    961 
    962 static void
    963 planar420cp(unsigned char *dst, const unsigned char *src, int dstPitch,
    964             int w, int h, int i420)
    965 {
    966     unsigned long srcUOffset, srcVOffset;
    967 
    968     /*
    969      * Blit luma component as a fake YUY2 assembler blit.
    970      */
    971     if (i420) {
    972         srcVOffset  = w * h + (w >> 1) * (h >> 1);
    973         srcUOffset = w * h;
    974     } else {
    975         srcUOffset  = w * h + (w >> 1) * (h >> 1);
    976         srcVOffset = w * h;
    977     }
    978 
    979     (*viaFastVidCpy) (dst, src, dstPitch, w >> 1, h, 1);
    980     UVBlit(dst + dstPitch * h, src + srcUOffset,
    981             src + srcVOffset, w >> 1, w >> 1, dstPitch, h >> 1);
    982 }
    983 
    984 /*
    985  * Slow and dirty. NV12 blit.
    986  */
    987 static void
    988 nv12cp(unsigned char *dst, const unsigned char *src, int dstPitch,
    989         int w, int h, int i420)
    990 {
    991     unsigned long srcUOffset, srcVOffset;
    992 
    993     /*
    994      * Blit luma component as a fake YUY2 assembler blit.
    995      */
    996     if (i420) {
    997         srcVOffset  = w * h + (w >> 1) * (h >> 1);
    998         srcUOffset = w * h;
    999     } else {
   1000         srcUOffset  = w * h + (w >> 1) * (h >> 1);
   1001         srcVOffset = w * h;
   1002     }
   1003 
   1004     (*viaFastVidCpy) (dst, src, dstPitch, w >> 1, h, TRUE);
   1005     nv12Blit(dst + dstPitch * h, src + srcUOffset,
   1006             src + srcVOffset, w >> 1, w >>1, dstPitch, h >> 1);
   1007 }
   1008 
   1009 #ifdef HAVE_DRI
   1010 
   1011 static int
   1012 viaDmaBlitImage(VIAPtr pVia,
   1013     viaPortPrivPtr pPort,
   1014     unsigned char *src,
   1015     CARD32 dst, unsigned width, unsigned height, unsigned lumaStride, int id)
   1016 {
   1017     Bool bounceBuffer;
   1018     drm_via_dmablit_t blit;
   1019     drm_via_blitsync_t *chromaSync = &blit.sync;
   1020     drm_via_blitsync_t lumaSync;
   1021     unsigned char *base;
   1022     unsigned char *bounceBase;
   1023     unsigned bounceStride;
   1024     unsigned bounceLines;
   1025     unsigned size;
   1026     int err = 0;
   1027     Bool nv12Conversion;
   1028 
   1029     bounceBuffer = ((unsigned long)src & 15);
   1030     nv12Conversion = (pVia->VideoEngine == VIDEO_ENGINE_CME &&
   1031                      (id == FOURCC_YV12 || id == FOURCC_I420));
   1032 
   1033     switch (id) {
   1034         case FOURCC_YUY2:
   1035         case FOURCC_RV15:
   1036         case FOURCC_RV16:
   1037             bounceStride = ALIGN_TO(2 * width, 16);
   1038             bounceLines = height;
   1039             break;
   1040         case FOURCC_RV32:
   1041             bounceStride = ALIGN_TO(4 * width, 16);
   1042             bounceLines = height;
   1043             break;
   1044 
   1045         case FOURCC_YV12:
   1046         case FOURCC_I420:
   1047         default:
   1048             bounceStride = ALIGN_TO(width, 16);
   1049             bounceLines = height;
   1050             break;
   1051     }
   1052 
   1053     if (bounceBuffer || nv12Conversion) {
   1054         if (!pPort->dmaBounceBuffer ||
   1055             pPort->dmaBounceStride != bounceStride ||
   1056             pPort->dmaBounceLines != bounceLines) {
   1057             if (pPort->dmaBounceBuffer) {
   1058                 free(pPort->dmaBounceBuffer);
   1059                 pPort->dmaBounceBuffer = 0;
   1060             }
   1061             size = bounceStride * bounceLines + 16;
   1062             if (id == FOURCC_YV12 || id == FOURCC_I420)
   1063                 size += ALIGN_TO(bounceStride >> 1, 16) * bounceLines;
   1064             pPort->dmaBounceBuffer = (unsigned char *)malloc(size);
   1065             pPort->dmaBounceLines = bounceLines;
   1066             pPort->dmaBounceStride = bounceStride;
   1067         }
   1068     }
   1069 
   1070     bounceBase =
   1071     (unsigned char *)ALIGN_TO((unsigned long)(pPort->dmaBounceBuffer),
   1072         16);
   1073     base = (bounceBuffer) ? bounceBase : src;
   1074 
   1075     if (bounceBuffer) {
   1076         (*viaFastVidCpy) (base, src, bounceStride, bounceStride >> 1, height,
   1077         1);
   1078     }
   1079 
   1080     blit.num_lines = height;
   1081     blit.line_length = bounceStride;
   1082     blit.fb_addr = dst;
   1083     blit.fb_stride = lumaStride;
   1084     blit.mem_addr = base;
   1085     blit.mem_stride = bounceStride;
   1086     blit.to_fb = 1;
   1087 #ifdef XV_DEBUG
   1088     ErrorF
   1089     ("Addr: 0x%lx, Offset 0x%lx\n Fb_stride: %u, Mem_stride: %u\n width: %u num_lines: %u\n",
   1090     (unsigned long)blit.mem_addr, (unsigned long)blit.fb_addr,
   1091     (unsigned)blit.fb_stride, (unsigned)blit.mem_stride,
   1092     (unsigned)blit.line_length, (unsigned)blit.num_lines);
   1093 #endif
   1094     while (-EAGAIN == (err =
   1095         drmCommandWriteRead(pVia->drmmode.fd, DRM_VIA_DMA_BLIT, &blit,
   1096         sizeof(blit)))) ;
   1097     if (err < 0)
   1098         return -1;
   1099 
   1100     lumaSync = blit.sync;
   1101 
   1102     if (id == FOURCC_YV12 || id == FOURCC_I420) {
   1103         unsigned tmp = ALIGN_TO(width >> 1, 16);
   1104 
   1105         if (nv12Conversion) {
   1106             nv12Blit(bounceBase + bounceStride * height,
   1107                 src + bounceStride * height + tmp * (height >> 1),
   1108                 src + bounceStride * height, width >> 1, tmp,
   1109                 bounceStride, height >> 1);
   1110         } else if (bounceBuffer) {
   1111             (*viaFastVidCpy) (base + bounceStride * height,
   1112                     src + bounceStride * height, tmp, tmp >> 1, height, 1);
   1113         }
   1114 
   1115         if (nv12Conversion) {
   1116             blit.num_lines = height >> 1;
   1117             blit.line_length = bounceStride;
   1118             blit.mem_addr = bounceBase + bounceStride * height;
   1119             blit.fb_stride = lumaStride;
   1120             blit.mem_stride = bounceStride;
   1121         } else {
   1122             blit.num_lines = height;
   1123             blit.line_length = tmp;
   1124             blit.mem_addr = base + bounceStride * height;
   1125             blit.fb_stride = lumaStride >> 1;
   1126             blit.mem_stride = tmp;
   1127         }
   1128 
   1129         blit.fb_addr = dst + lumaStride * height;
   1130         blit.to_fb = 1;
   1131 
   1132         while (-EAGAIN == (err =
   1133             drmCommandWriteRead(pVia->drmmode.fd, DRM_VIA_DMA_BLIT, &blit,
   1134                 sizeof(blit))));
   1135         if (err < 0)
   1136             return -1;
   1137     }
   1138 
   1139     while (-EAGAIN == (err = drmCommandWrite(pVia->drmmode.fd, DRM_VIA_BLIT_SYNC,
   1140         chromaSync, sizeof(*chromaSync)))) ;
   1141     if (err < 0)
   1142         return -1;
   1143 
   1144     return Success;
   1145 }
   1146 
   1147 #endif
   1148 
   1149 
   1150 /*
   1151  * The source rectangle of the video is defined by (src_x, src_y, src_w, src_h).
   1152  * The dest rectangle of the video is defined by (drw_x, drw_y, drw_w, drw_h).
   1153  * id is a fourcc code for the format of the video.
   1154  * buf is the pointer to the source data in system memory.
   1155  * width and height are the w/h of the source data.
   1156  * If "sync" is TRUE, then we must be finished with *buf at the point of return
   1157  * (which we always are).
   1158  * clipBoxes is the clipping region in screen space.
   1159  * data is a pointer to our port private.
   1160  * pDraw is a Drawable, which might not be the screen in the case of
   1161  * compositing.  It's a new argument to the function in the 1.1 server.
   1162  */
   1163 
   1164 static int
   1165 viaPutImage(ScrnInfoPtr pScrn,
   1166         short src_x, short src_y,
   1167         short drw_x, short drw_y,
   1168         short src_w, short src_h,
   1169         short drw_w, short drw_h,
   1170         int id, unsigned char *buf,
   1171         short width, short height, Bool sync, RegionPtr clipBoxes,
   1172         pointer data, DrawablePtr pDraw)
   1173 {
   1174     VIAPtr pVia = VIAPTR(pScrn);
   1175     viaPortPrivPtr pPriv = (viaPortPrivPtr) data;
   1176     xf86CrtcPtr crtc = NULL;
   1177     unsigned long retCode;
   1178 
   1179 # ifdef XV_DEBUG
   1180     ErrorF(" via_xv.c : viaPutImage : called,  Screen[%d]\n", pScrn->scrnIndex);
   1181     ErrorF(" via_xv.c : FourCC=0x%x width=%d height=%d sync=%d\n", id,
   1182             width, height, sync);
   1183     ErrorF
   1184     (" via_xv.c : src_x=%d src_y=%d src_w=%d src_h=%d colorkey=0x%lx\n",
   1185             src_x, src_y, src_w, src_h, pPriv->colorKey);
   1186     ErrorF(" via_xv.c : drw_x=%d drw_y=%d drw_w=%d drw_h=%d\n", drw_x,
   1187             drw_y, drw_w, drw_h);
   1188 # endif
   1189 
   1190     /* Find out which CRTC the surface will belong to */
   1191     crtc = window_belongs_to_crtc(pScrn, drw_x, drw_y, drw_w, drw_h);
   1192     if (!crtc) {
   1193         DBG_DD(ErrorF(" via_xv.c : No usable CRTC\n"));
   1194         viaXvError(pScrn, pPriv, xve_adaptor);
   1195         return BadAlloc;
   1196     }
   1197 
   1198     switch (pPriv->xv_adaptor) {
   1199         case XV_ADAPT_SWOV:
   1200         {
   1201             DDUPDATEOVERLAY UpdateOverlay_Video;
   1202             LPDDUPDATEOVERLAY lpUpdateOverlay = &UpdateOverlay_Video;
   1203 
   1204             int dstPitch;
   1205             unsigned long dwUseExtendedFIFO = 0;
   1206 
   1207             DBG_DD(ErrorF(" via_xv.c :              : S/W Overlay! \n"));
   1208             /*  Allocate video memory(CreateSurface),
   1209              *  add codes to judge if need to re-create surface
   1210              */
   1211             if ((pPriv->old_src_w != src_w) || (pPriv->old_src_h != src_h)) {
   1212                 ViaSwovSurfaceDestroy(pScrn, pPriv);
   1213             }
   1214 
   1215             if (Success != (retCode =
   1216                 ViaSwovSurfaceCreate(pScrn, pPriv, id, width, height))) {
   1217                 DBG_DD(ErrorF
   1218                         ("             : Fail to Create SW Video Surface\n"));
   1219                 viaXvError(pScrn, pPriv, xve_mem);
   1220                 return retCode;
   1221             }
   1222 
   1223             /*  Copy image data from system memory to video memory
   1224              *  TODO: use DRM's DMA feature to accelerate data copy
   1225              */
   1226             if (id != FOURCC_XVMC) {
   1227                 dstPitch = pVia->swov.SWDevice.dwPitch;
   1228 
   1229                 if (pVia->useDmaBlit) {
   1230 #ifdef HAVE_DRI
   1231                     if (viaDmaBlitImage(pVia, pPriv, buf,
   1232                         (CARD32) pVia->swov.SWDevice.dwSWPhysicalAddr[pVia->dwFrameNum & 1],
   1233                         width, height, dstPitch, id)) {
   1234                             viaXvError(pScrn, pPriv, xve_dmablit);
   1235                         return BadAccess;
   1236                     }
   1237 #endif
   1238                 } else {
   1239                     switch (id) {
   1240                         case FOURCC_I420:
   1241                             if (pVia->VideoEngine == VIDEO_ENGINE_CME) {
   1242                                 nv12cp(pVia->swov.SWDevice.
   1243                                     lpSWOverlaySurface[pVia->dwFrameNum & 1],
   1244                                     buf, dstPitch, width, height, 1);
   1245                             } else {
   1246                                 (*viaFastVidCpy)(pVia->swov.SWDevice.
   1247                                     lpSWOverlaySurface[pVia->dwFrameNum & 1],
   1248                                     buf, dstPitch, width, height, 0);
   1249                             }
   1250                             break;
   1251                         case FOURCC_YV12:
   1252                             if (pVia->VideoEngine == VIDEO_ENGINE_CME) {
   1253                                 nv12cp(pVia->swov.SWDevice.
   1254                                     lpSWOverlaySurface[pVia->dwFrameNum & 1],
   1255                                     buf, dstPitch, width, height, 0);
   1256                             } else {
   1257                                 (*viaFastVidCpy)(pVia->swov.SWDevice.
   1258                                     lpSWOverlaySurface[pVia->dwFrameNum & 1],
   1259                                     buf, dstPitch, width, height, 0);
   1260                             }
   1261                             break;
   1262                         case FOURCC_RV32:
   1263                             (*viaFastVidCpy) (pVia->swov.SWDevice.
   1264                                 lpSWOverlaySurface[pVia->dwFrameNum & 1],
   1265                                 buf, dstPitch, width << 1, height, 1);
   1266                             break;
   1267                         case FOURCC_UYVY:
   1268                         case FOURCC_YUY2:
   1269                         case FOURCC_RV15:
   1270                         case FOURCC_RV16:
   1271                         default:
   1272                             (*viaFastVidCpy) (pVia->swov.SWDevice.
   1273                                 lpSWOverlaySurface[pVia->dwFrameNum & 1],
   1274                                 buf, dstPitch, width, height, 1);
   1275                             break;
   1276                     }
   1277                 }
   1278             }
   1279 
   1280             /* If there is bandwidth issue, block the H/W overlay */
   1281             if (!(DecideOverlaySupport(crtc))) {
   1282                 DBG_DD(ErrorF
   1283                         (" via_xv.c : Xv Overlay rejected due to insufficient "
   1284                                 "memory bandwidth.\n"));
   1285                 viaXvError(pScrn, pPriv, xve_bandwidth);
   1286                 return BadAlloc;
   1287             }
   1288 
   1289             /*
   1290              *  fill video overlay parameter
   1291              */
   1292             lpUpdateOverlay->SrcLeft = src_x;
   1293             lpUpdateOverlay->SrcTop = src_y;
   1294             lpUpdateOverlay->SrcRight = src_x + src_w;
   1295             lpUpdateOverlay->SrcBottom = src_y + src_h;
   1296 
   1297             lpUpdateOverlay->DstLeft = drw_x;
   1298             lpUpdateOverlay->DstTop = drw_y;
   1299             lpUpdateOverlay->DstRight = drw_x + drw_w;
   1300             lpUpdateOverlay->DstBottom = drw_y + drw_h;
   1301 
   1302             lpUpdateOverlay->dwFlags = DDOVER_KEYDEST;
   1303 
   1304             if (pScrn->bitsPerPixel == 8) {
   1305                 lpUpdateOverlay->dwColorSpaceLowValue = pPriv->colorKey & 0xff;
   1306             } else {
   1307                 lpUpdateOverlay->dwColorSpaceLowValue = pPriv->colorKey;
   1308             }
   1309             /* If use extend FIFO mode */
   1310             if (pScrn->currentMode->HDisplay > 1024) {
   1311                 dwUseExtendedFIFO = 1;
   1312             }
   1313 
   1314             if (FOURCC_XVMC != id) {
   1315 
   1316                 /*
   1317                  * XvMC flipping is done in the client lib.
   1318                  */
   1319 
   1320                 DBG_DD(ErrorF("             : Flip\n"));
   1321                 Flip(pVia, pPriv, id, pVia->dwFrameNum & 1);
   1322             }
   1323 
   1324             pVia->dwFrameNum++;
   1325 
   1326             /* If the dest rec. & extendFIFO doesn't change, don't do UpdateOverlay
   1327              * unless the surface clipping has changed */
   1328             if ((pPriv->old_drw_x == drw_x) && (pPriv->old_drw_y == drw_y)
   1329                     && (pPriv->old_drw_w == drw_w) && (pPriv->old_drw_h == drw_h)
   1330                     && (pPriv->old_src_x == src_x) && (pPriv->old_src_y == src_y)
   1331                     && (pPriv->old_src_w == src_w) && (pPriv->old_src_h == src_h)
   1332                     && (pVia->old_dwUseExtendedFIFO == dwUseExtendedFIFO)
   1333                     && (pVia->VideoStatus & VIDEO_SWOV_ON) &&
   1334                     REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) {
   1335                 DBG_DD(ErrorF(" via_xv.c : don't do UpdateOverlay! \n"));
   1336                 viaXvError(pScrn, pPriv, xve_none);
   1337                 return Success;
   1338             }
   1339 
   1340             pPriv->old_src_x = src_x;
   1341             pPriv->old_src_y = src_y;
   1342             pPriv->old_src_w = src_w;
   1343             pPriv->old_src_h = src_h;
   1344 
   1345             pPriv->old_drw_x = drw_x;
   1346             pPriv->old_drw_y = drw_y;
   1347             pPriv->old_drw_w = drw_w;
   1348             pPriv->old_drw_h = drw_h;
   1349             pVia->old_dwUseExtendedFIFO = dwUseExtendedFIFO;
   1350             pVia->VideoStatus |= VIDEO_SWOV_ON;
   1351 
   1352             /*  BitBlt: Draw the colorkey rectangle */
   1353             if (!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) {
   1354                 REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
   1355                 if (pPriv->autoPaint) {
   1356                     if (pDraw->type == DRAWABLE_WINDOW) {
   1357                         xf86XVFillKeyHelperDrawable(pDraw, pPriv->colorKey, clipBoxes);
   1358                         DamageDamageRegion(pDraw, clipBoxes);
   1359                     } else {
   1360                         xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
   1361                     }
   1362                 }
   1363             } else {
   1364                 DBG_DD(ErrorF(" via_xv.c : // No need to draw Colorkey!! \n"));
   1365             }
   1366             /*
   1367              *  Update video overlay
   1368              */
   1369             if (!VIAVidUpdateOverlay(crtc, lpUpdateOverlay)) {
   1370                 DBG_DD(ErrorF
   1371                         (" via_xv.c : call v4l updateoverlay fail. \n"));
   1372             } else {
   1373                 DBG_DD(ErrorF(" via_xv.c : PutImage done OK\n"));
   1374                 viaXvError(pScrn, pPriv, xve_none);
   1375                 return Success;
   1376             }
   1377             break;
   1378         }
   1379         default:
   1380             DBG_DD(ErrorF(" via_xv.c : XVPort not supported\n"));
   1381             viaXvError(pScrn, pPriv, xve_adaptor);
   1382             break;
   1383     }
   1384     DBG_DD(ErrorF(" via_xv.c : PutImage done OK\n"));
   1385     viaXvError(pScrn, pPriv, xve_none);
   1386     return Success;
   1387 }
   1388 
   1389 static int
   1390 viaQueryImageAttributes(ScrnInfoPtr pScrn,
   1391         int id, unsigned short *w, unsigned short *h, int *pitches,
   1392         int *offsets)
   1393 {
   1394     int size, tmp;
   1395     VIAPtr pVia = VIAPTR(pScrn);
   1396 
   1397     DBG_DD(ErrorF(" via_xv.c : viaQueryImageAttributes : FourCC=0x%x, ",
   1398             id));
   1399     DBG_DD(ErrorF(" via_xv.c : Screen[%d],  w=%d, h=%d\n", pScrn->scrnIndex, *w, *h));
   1400 
   1401     if ((!w) || (!h))
   1402         return 0;
   1403 
   1404     if (*w > VIA_MAX_XVIMAGE_X)
   1405         *w = VIA_MAX_XVIMAGE_X;
   1406     if (*h > VIA_MAX_XVIMAGE_Y)
   1407         *h = VIA_MAX_XVIMAGE_Y;
   1408 
   1409     *w = (*w + 1) & ~1;
   1410     if (offsets)
   1411         offsets[0] = 0;
   1412 
   1413     switch (id) {
   1414         case FOURCC_I420:
   1415         case FOURCC_YV12: /*Planar format : YV12 -4:2:0 */
   1416             *h = (*h + 1) & ~1;
   1417             size = *w;
   1418             if (pVia->useDmaBlit)
   1419                 size = (size + 15) & ~15;
   1420             if (pitches)
   1421                 pitches[0] = size;
   1422             size *= *h;
   1423             if (offsets)
   1424                 offsets[1] = size;
   1425             tmp = (*w >> 1);
   1426             if (pVia->useDmaBlit)
   1427                 tmp = (tmp + 15) & ~15;
   1428             if (pitches)
   1429                 pitches[1] = pitches[2] = tmp;
   1430             tmp *= (*h >> 1);
   1431             size += tmp;
   1432             if (offsets)
   1433                 offsets[2] = size;
   1434             size += tmp;
   1435             break;
   1436         case FOURCC_XVMC:
   1437             *h = (*h + 1) & ~1;
   1438 #ifdef HAVE_DRI
   1439             size = viaXvMCPutImageSize(pScrn);
   1440 #else
   1441             size = 0;
   1442 #endif
   1443             if (pitches)
   1444                 pitches[0] = size;
   1445             break;
   1446         case FOURCC_AI44:
   1447         case FOURCC_IA44:
   1448             size = *w * *h;
   1449             if (pitches)
   1450                 pitches[0] = *w;
   1451             if (offsets)
   1452                 offsets[0] = 0;
   1453             break;
   1454         case FOURCC_RV32:
   1455             size = *w << 2;
   1456             if (pVia->useDmaBlit)
   1457                 size = (size + 15) & ~15;
   1458             if (pitches)
   1459                 pitches[0] = size;
   1460             size *= *h;
   1461             break;
   1462         case FOURCC_UYVY: /*Packed format : UYVY -4:2:2 */
   1463         case FOURCC_YUY2: /*Packed format : YUY2 -4:2:2 */
   1464         case FOURCC_RV15:
   1465         case FOURCC_RV16:
   1466         default:
   1467             size = *w << 1;
   1468             if (pVia->useDmaBlit)
   1469                 size = (size + 15) & ~15;
   1470             if (pitches)
   1471                 pitches[0] = size;
   1472             size *= *h;
   1473         break;
   1474     }
   1475 
   1476     if (pitches)
   1477         DBG_DD(ErrorF(" pitches[0]=%d, pitches[1]=%d, pitches[2]=%d, ",
   1478                     pitches[0], pitches[1], pitches[2]));
   1479     if (offsets)
   1480         DBG_DD(ErrorF(" offsets[0]=%d, offsets[1]=%d, offsets[2]=%d, ",
   1481                     offsets[0], offsets[1], offsets[2]));
   1482 
   1483     DBG_DD(ErrorF(" width=%d, height=%d \n", *w, *h));
   1484     return size;
   1485 }
   1486 
   1487 /*
   1488  *
   1489  */
   1490 void
   1491 VIAVidAdjustFrame(ScrnInfoPtr pScrn, int x, int y)
   1492 {
   1493     VIAPtr pVia = VIAPTR(pScrn);
   1494 
   1495     pVia->swov.panning_x = x;
   1496     pVia->swov.panning_y = y;
   1497 }
   1498 
   1499 /*
   1500  * Blit the U and V Fields. Used to Flip the U V for I420.
   1501  */
   1502 
   1503 static void
   1504 UVBlit(unsigned char *dst,
   1505         const unsigned char *uBuffer,
   1506         const unsigned char *vBuffer,
   1507         unsigned width, unsigned srcPitch, unsigned dstPitch, unsigned lines)
   1508 {
   1509     int i, j;
   1510 
   1511     dstPitch >>= 1;
   1512 
   1513     for(j = 0; j < lines; j++)
   1514     {
   1515         for(i = 0; i < width; i++)
   1516         {
   1517             dst[i] = (uBuffer[i] << 8) | (vBuffer[i] << 16);
   1518         }
   1519 
   1520         dst += dstPitch;
   1521         uBuffer += srcPitch;
   1522         vBuffer += srcPitch;
   1523     }
   1524 
   1525 }
   1526 
   1527 
   1528 /*
   1529  * Blit the chroma field from one buffer to another while at the same time converting from
   1530  * YV12 to NV12.
   1531  */
   1532 
   1533 static void
   1534 nv12Blit(unsigned char *nv12Chroma,
   1535         const unsigned char *uBuffer,
   1536         const unsigned char *vBuffer,
   1537         unsigned width, unsigned srcPitch, unsigned dstPitch, unsigned lines)
   1538 {
   1539     int x;
   1540     int dstAdd;
   1541     int srcAdd;
   1542 
   1543     dstAdd = dstPitch - (width << 1);
   1544     srcAdd = srcPitch - width;
   1545 
   1546     while (lines--) {
   1547         x = width;
   1548         while (x > 3) {
   1549             register CARD32
   1550             dst32,
   1551             src32 = *((CARD32 *) vBuffer),
   1552             src32_2 = *((CARD32 *) uBuffer);
   1553             dst32 =
   1554                 (src32_2 & 0xff) | ((src32 & 0xff) << 8) |
   1555                 ((src32_2 & 0x0000ff00) << 8) | ((src32 & 0x0000ff00) << 16);
   1556             *((CARD32 *) nv12Chroma) = dst32;
   1557             nv12Chroma += 4;
   1558             dst32 =
   1559                 ((src32_2 & 0x00ff0000) >> 16) | ((src32 & 0x00ff0000) >> 8) |
   1560                 ((src32_2 & 0xff000000) >> 8) | (src32 & 0xff000000);
   1561             *((CARD32 *) nv12Chroma) = dst32;
   1562             nv12Chroma += 4;
   1563             x -= 4;
   1564             vBuffer += 4;
   1565             uBuffer += 4;
   1566         }
   1567         while (x--) {
   1568             *nv12Chroma++ = *uBuffer++;
   1569             *nv12Chroma++ = *vBuffer++;
   1570         }
   1571         nv12Chroma += dstAdd;
   1572         vBuffer += srcAdd;
   1573         uBuffer += srcAdd;
   1574     }
   1575 }
   1576 
   1577 #endif /* !XvExtension */
   1578