Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (c) 2011 Intel Corporation. All Rights Reserved.
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the
      6  * "Software"), to deal in the Software without restriction, including
      7  * without limitation the rights to use, copy, modify, merge, publish,
      8  * distribute, sub license, and/or sell copies of the Software, and to
      9  * permit persons to whom the Software is furnished to do so, subject to
     10  * 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
     17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
     19  * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
     20  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     21  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     22  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     23  *
     24  * Authors:
     25  *    Shengquan Yuan  <shengquan.yuan (at) intel.com>
     26  *    Binglin Chen <binglin.chen (at) intel.com>
     27  *    Jason Hu <jason.hu (at) intel.com>
     28  *    Zeng Li <zeng.li (at) intel.com>
     29  */
     30 
     31 /*
     32  * Most of rendering codes are ported from xf86-video-i810/src/i810_overlay.c
     33  */
     34 
     35 #include <errno.h>
     36 #include <stdlib.h>
     37 #include <unistd.h>
     38 #include <stdio.h>
     39 #include <math.h>
     40 #include <va/va_backend.h>
     41 #include <wsbm/wsbm_manager.h>
     42 #include "psb_drv_video.h"
     43 #include "psb_output.h"
     44 #include "psb_overlay.h"
     45 #include "psb_drv_debug.h"
     46 
     47 #ifdef ANDROID
     48 #define psb_xrandr_single_mode() 0
     49 #else
     50 int psb_xrandr_single_mode();
     51 #endif
     52 
     53 #define INIT_DRIVER_DATA    psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData
     54 #define SURFACE(id) ((object_surface_p) object_heap_lookup( &driver_data->surface_heap, id ))
     55 #define CONTEXT(id) ((object_context_p) object_heap_lookup( &driver_data->context_heap, id ))
     56 //#define GET_SURFACE_INFO_rotate(psb_surface) ((int) (psb_surface)->extra_info[5])
     57 
     58 #ifndef VA_FOURCC_I420
     59 #define VA_FOURCC_I420          0x30323449
     60 #endif
     61 
     62 /**********************************************************************************************
     63  * I830ResetVideo
     64  *
     65  * Description: Use this function to reset the overlay register back buffer to its default
     66  * values.  Note that this function does not actually apply these values.  To do so, please
     67  * write to OVADD.
     68  **********************************************************************************************/
     69 static void
     70 I830ResetVideo(VADriverContextP ctx, PsbPortPrivPtr pPriv)
     71 {
     72     INIT_DRIVER_DATA;
     73     I830OverlayRegPtr overlayA = (I830OverlayRegPtr)(pPriv->regmap[0]);
     74     I830OverlayRegPtr overlayC = (I830OverlayRegPtr)(pPriv->regmap[1]);
     75 
     76     memset(overlayA, 0, sizeof(*overlayA));
     77     memset(overlayC, 0, sizeof(*overlayC));
     78 
     79     overlayA->OCLRC0 = (pPriv->contrast.Value << 18) | (pPriv->brightness.Value & 0xff);
     80     overlayA->OCLRC1 = pPriv->saturation.Value;
     81 
     82     overlayC->OCLRC0 = (pPriv->contrast.Value << 18) | (pPriv->brightness.Value & 0xff);
     83     overlayC->OCLRC1 = pPriv->saturation.Value;
     84 
     85 #if USE_DCLRK
     86     /* case bit depth 16 */
     87     overlayA->DCLRKV = pPriv->colorKey;
     88     overlayA->DCLRKM |= DEST_KEY_ENABLE;
     89     overlayA->DCLRKM &= ~CONST_ALPHA_ENABLE;
     90 
     91     overlayC->DCLRKV = pPriv->colorKey;
     92     overlayC->DCLRKM |= DEST_KEY_ENABLE;
     93     overlayC->DCLRKM &= ~CONST_ALPHA_ENABLE;
     94 #else
     95     overlayA->DCLRKM &= ~DEST_KEY_ENABLE;
     96     overlayC->DCLRKM &= ~DEST_KEY_ENABLE;
     97 #endif
     98     overlayA->DWINSZ = 0x00000000;
     99     overlayA->OCONFIG = CC_OUT_8BIT;
    100 
    101     overlayC->DWINSZ = 0x00000000;
    102     overlayC->OCONFIG = CC_OUT_8BIT;
    103 }
    104 
    105 static uint32_t I830BoundGammaElt(uint32_t elt, uint32_t eltPrev)
    106 {
    107     elt &= 0xff;
    108     eltPrev &= 0xff;
    109     if (elt < eltPrev)
    110         elt = eltPrev;
    111     else if ((elt - eltPrev) > 0x7e)
    112         elt = eltPrev + 0x7e;
    113     return elt;
    114 }
    115 
    116 static uint32_t I830BoundGamma(uint32_t gamma, uint32_t gammaPrev)
    117 {
    118     return (I830BoundGammaElt(gamma >> 24, gammaPrev >> 24) << 24 |
    119             I830BoundGammaElt(gamma >> 16, gammaPrev >> 16) << 16 |
    120             I830BoundGammaElt(gamma >>  8, gammaPrev >>  8) <<  8 |
    121             I830BoundGammaElt(gamma      , gammaPrev));
    122 }
    123 
    124 static void
    125 I830UpdateGamma(VADriverContextP ctx, PsbPortPrivPtr pPriv)
    126 {
    127 #ifndef BAYTRAIL
    128     INIT_DRIVER_DATA;
    129     uint32_t gamma0 = pPriv->gamma0;
    130     uint32_t gamma1 = pPriv->gamma1;
    131     uint32_t gamma2 = pPriv->gamma2;
    132     uint32_t gamma3 = pPriv->gamma3;
    133     uint32_t gamma4 = pPriv->gamma4;
    134     uint32_t gamma5 = pPriv->gamma5;
    135     struct drm_psb_register_rw_arg regs;
    136 
    137     gamma1 = I830BoundGamma(gamma1, gamma0);
    138     gamma2 = I830BoundGamma(gamma2, gamma1);
    139     gamma3 = I830BoundGamma(gamma3, gamma2);
    140     gamma4 = I830BoundGamma(gamma4, gamma3);
    141     gamma5 = I830BoundGamma(gamma5, gamma4);
    142 
    143     memset(&regs, 0, sizeof(regs));
    144     if (pPriv->is_mfld)
    145         regs.overlay_write_mask |= OV_REGRWBITS_OGAM_ALL | OVC_REGRWBITS_OGAM_ALL;
    146     else
    147         regs.overlay_write_mask |= OV_REGRWBITS_OGAM_ALL;
    148     regs.overlay.OGAMC0 = gamma0;
    149     regs.overlay.OGAMC1 = gamma1;
    150     regs.overlay.OGAMC2 = gamma2;
    151     regs.overlay.OGAMC3 = gamma3;
    152     regs.overlay.OGAMC4 = gamma4;
    153     regs.overlay.OGAMC5 = gamma5;
    154     drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, &regs, sizeof(regs));
    155 #endif
    156 }
    157 
    158 static void I830StopVideo(VADriverContextP ctx)
    159 {
    160 #ifndef BAYTRAIL
    161     INIT_DRIVER_DATA;
    162     PsbPortPrivPtr pPriv = (PsbPortPrivPtr)(&driver_data->coverlay_priv);
    163     I830OverlayRegPtr overlayA, overlayC;
    164     struct drm_psb_register_rw_arg regs;
    165 
    166     if (!pPriv->overlayA_enabled && !pPriv->overlayC_enabled) {
    167         drv_debug_msg(VIDEO_DEBUG_GENERAL, "I830StopVideo : no overlay has been enabled, do nothing.\n");
    168         return;
    169     }
    170 
    171     overlayA = (I830OverlayRegPtr)(pPriv->regmap[0]);
    172     overlayC = (I830OverlayRegPtr)(pPriv->regmap[1]);
    173 #if 0
    174     REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
    175 #endif
    176     memset(&regs, 0, sizeof(regs));
    177     if (pPriv->subpicture_enabled) {
    178         regs.subpicture_disable_mask = pPriv->subpicture_enable_mask;
    179         pPriv->subpicture_enabled = 0;
    180         drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, &regs, sizeof(regs));
    181     }
    182 
    183     memset(&regs, 0, sizeof(regs));
    184 
    185     if (pPriv->is_mfld && psb_xrandr_single_mode() == 0) {
    186         if (pPriv->overlayC_enabled) {
    187             regs.overlay_read_mask = OVC_REGRWBITS_OVADD;
    188             drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, &regs, sizeof(regs));
    189 
    190             overlayC->DWINSZ = 0x00000000;
    191             overlayC->OCMD &= ~OVERLAY_ENABLE;
    192             regs.overlay_read_mask = 0;
    193             regs.overlay_write_mask = OVC_REGRWBITS_OVADD;
    194             regs.overlay.b_wait_vblank = 1;
    195             drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, &regs, sizeof(regs));
    196 
    197             memset(&regs, 0, sizeof(regs));
    198             pPriv->overlayC_enabled = 0;
    199         }
    200         if (pPriv->overlayA_enabled) {
    201             regs.overlay_read_mask = OV_REGRWBITS_OVADD;
    202             drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, &regs, sizeof(regs));
    203 
    204             overlayA->DWINSZ = 0x00000000;
    205             overlayA->OCMD &= ~OVERLAY_ENABLE;
    206             regs.overlay_read_mask = 0;
    207             regs.overlay_write_mask = OV_REGRWBITS_OVADD;
    208             regs.overlay.b_wait_vblank = 1;
    209             drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, &regs, sizeof(regs));
    210             pPriv->overlayA_enabled = 0;
    211         }
    212     } else {
    213         regs.overlay_read_mask = OV_REGRWBITS_OVADD;
    214         drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, &regs, sizeof(regs));
    215 
    216         overlayA->DWINSZ = 0x00000000;
    217         overlayA->OCMD &= ~OVERLAY_ENABLE;
    218         regs.overlay_read_mask = 0;
    219         regs.overlay_write_mask = OV_REGRWBITS_OVADD;
    220         regs.overlay.b_wait_vblank = 1;
    221         drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, &regs, sizeof(regs));
    222         pPriv->overlayA_enabled = 0;
    223     }
    224 #endif
    225 }
    226 
    227 #if 0
    228 static void I830SwitchPipe(VADriverContextP ctx , int overlayId, int pipeId)
    229 {
    230     INIT_DRIVER_DATA;
    231     PsbPortPrivPtr pPriv = (PsbPortPrivPtr)(&driver_data->coverlay_priv);
    232     I830OverlayRegPtr overlay = (I830OverlayRegPtr)(pPriv->regmap[overlayId]);
    233     struct drm_psb_register_rw_arg regs;
    234     uint32_t overlay_mask;
    235 
    236     if ((overlayId == OVERLAY_A) && pPriv->overlayA_enabled)
    237         overlay_mask = OV_REGRWBITS_OVADD;
    238     else if ((overlayId == OVERLAY_C) && pPriv->overlayC_enabled)
    239         overlay_mask = OVC_REGRWBITS_OVADD;
    240     else
    241         return;  /*No overlay enabled, do nothing.*/
    242 
    243     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Overlay %d switch to pipe %d\n", overlayId, pipeId);
    244     memset(&regs, 0, sizeof(regs));
    245     memset(overlay, 0, sizeof(*overlay));
    246     overlay->OCLRC0 = (pPriv->contrast.Value << 18) | (pPriv->brightness.Value & 0xff);
    247     overlay->OCLRC1 = pPriv->saturation.Value;
    248 
    249     /* case bit depth 16 */
    250     overlay->DCLRKV = pPriv->colorKey;
    251     overlay->DCLRKM |= DEST_KEY_ENABLE;
    252     overlay->DCLRKM &= ~CONST_ALPHA_ENABLE;
    253     overlay->DWINSZ = 0x00000000;
    254     overlay->OCONFIG = CC_OUT_8BIT;
    255 
    256     regs.overlay_read_mask = overlay_mask;
    257     drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, &regs, sizeof(regs));
    258 
    259     switch (pipeId) {
    260     case PIPEA:
    261         overlay->OCONFIG |= OVERLAY_C_PIPE_A;
    262         break;
    263     case PIPEB:
    264         overlay->OCONFIG |= OVERLAY_C_PIPE_B;
    265         break;
    266     case PIPEC:
    267         overlay->OCONFIG |= OVERLAY_C_PIPE_C;
    268         break;
    269     }
    270     regs.overlay_read_mask = 0;
    271     regs.overlay_write_mask = overlay_mask;
    272     regs.overlay.b_wait_vblank = 1;
    273     drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, &regs, sizeof(regs));
    274 }
    275 #endif
    276 
    277 static int
    278 i830_swidth(unsigned int offset, unsigned int width, unsigned int mask, int shift)
    279 {
    280     int swidth = ((offset + width + mask) >> shift) - (offset >> shift);
    281     swidth <<= 1;
    282     swidth -= 1;
    283     return swidth << 2;
    284 }
    285 
    286 static Bool
    287 SetCoeffRegs(double *coeff, int mantSize, coeffPtr pCoeff, int pos)
    288 {
    289     int maxVal, icoeff, res;
    290     int sign;
    291     double c;
    292 
    293     sign = 0;
    294     maxVal = 1 << mantSize;
    295     c = *coeff;
    296     if (c < 0.0) {
    297         sign = 1;
    298         c = -c;
    299     }
    300 
    301     res = 12 - mantSize;
    302     if ((icoeff = (int)(c * 4 * maxVal + 0.5)) < maxVal) {
    303         pCoeff[pos].exponent = 3;
    304         pCoeff[pos].mantissa = icoeff << res;
    305         *coeff = (double)icoeff / (double)(4 * maxVal);
    306     } else if ((icoeff = (int)(c * 2 * maxVal + 0.5)) < maxVal) {
    307         pCoeff[pos].exponent = 2;
    308         pCoeff[pos].mantissa = icoeff << res;
    309         *coeff = (double)icoeff / (double)(2 * maxVal);
    310     } else if ((icoeff = (int)(c * maxVal + 0.5)) < maxVal) {
    311         pCoeff[pos].exponent = 1;
    312         pCoeff[pos].mantissa = icoeff << res;
    313         *coeff = (double)icoeff / (double)(maxVal);
    314     } else if ((icoeff = (int)(c * maxVal * 0.5 + 0.5)) < maxVal) {
    315         pCoeff[pos].exponent = 0;
    316         pCoeff[pos].mantissa = icoeff << res;
    317         *coeff = (double)icoeff / (double)(maxVal / 2);
    318     } else {
    319         /* Coeff out of range */
    320         return FALSE;
    321     }
    322 
    323     pCoeff[pos].sign = sign;
    324     if (sign)
    325         *coeff = -(*coeff);
    326     return TRUE;
    327 }
    328 
    329 static void
    330 UpdateCoeff(int taps, double fCutoff, Bool isHoriz, Bool isY, coeffPtr pCoeff)
    331 {
    332     int i, j, j1, num, pos, mantSize;
    333     double pi = 3.1415926535, val, sinc, window, sum;
    334     double rawCoeff[MAX_TAPS * 32], coeffs[N_PHASES][MAX_TAPS];
    335     double diff;
    336     int tapAdjust[MAX_TAPS], tap2Fix;
    337     Bool isVertAndUV;
    338 
    339     if (isHoriz)
    340         mantSize = 7;
    341     else
    342         mantSize = 6;
    343 
    344     isVertAndUV = !isHoriz && !isY;
    345     num = taps * 16;
    346     for (i = 0; i < num  * 2; i++) {
    347         val = (1.0 / fCutoff) * taps * pi * (i - num) / (2 * num);
    348         if (val == 0.0)
    349             sinc = 1.0;
    350         else
    351             sinc = sin(val) / val;
    352 
    353         /* Hamming window */
    354         window = (0.5 - 0.5 * cos(i * pi / num));
    355         rawCoeff[i] = sinc * window;
    356     }
    357 
    358     for (i = 0; i < N_PHASES; i++) {
    359         /* Normalise the coefficients. */
    360         sum = 0.0;
    361         for (j = 0; j < taps; j++) {
    362             pos = i + j * 32;
    363             sum += rawCoeff[pos];
    364         }
    365         for (j = 0; j < taps; j++) {
    366             pos = i + j * 32;
    367             coeffs[i][j] = rawCoeff[pos] / sum;
    368         }
    369 
    370         /* Set the register values. */
    371         for (j = 0; j < taps; j++) {
    372             pos = j + i * taps;
    373             if ((j == (taps - 1) / 2) && !isVertAndUV)
    374                 SetCoeffRegs(&coeffs[i][j], mantSize + 2, pCoeff, pos);
    375             else
    376                 SetCoeffRegs(&coeffs[i][j], mantSize, pCoeff, pos);
    377         }
    378 
    379         tapAdjust[0] = (taps - 1) / 2;
    380         for (j = 1, j1 = 1; j <= tapAdjust[0]; j++, j1++) {
    381             tapAdjust[j1] = tapAdjust[0] - j;
    382             tapAdjust[++j1] = tapAdjust[0] + j;
    383         }
    384 
    385         /* Adjust the coefficients. */
    386         sum = 0.0;
    387         for (j = 0; j < taps; j++)
    388             sum += coeffs[i][j];
    389         if (sum != 1.0) {
    390             for (j1 = 0; j1 < taps; j1++) {
    391                 tap2Fix = tapAdjust[j1];
    392                 diff = 1.0 - sum;
    393                 coeffs[i][tap2Fix] += diff;
    394                 pos = tap2Fix + i * taps;
    395                 if ((tap2Fix == (taps - 1) / 2) && !isVertAndUV)
    396                     SetCoeffRegs(&coeffs[i][tap2Fix], mantSize + 2, pCoeff, pos);
    397                 else
    398                     SetCoeffRegs(&coeffs[i][tap2Fix], mantSize, pCoeff, pos);
    399 
    400                 sum = 0.0;
    401                 for (j = 0; j < taps; j++)
    402                     sum += coeffs[i][j];
    403                 if (sum == 1.0)
    404                     break;
    405             }
    406         }
    407     }
    408 }
    409 
    410 static void
    411 i830_display_video(
    412     VADriverContextP ctx, PsbPortPrivPtr pPriv, VASurfaceID __maybe_unused surface,
    413     int id, short width, short height,
    414     int dstPitch, int srcPitch, int __maybe_unused x1, int __maybe_unused y1, int __maybe_unused x2, int __maybe_unused y2, BoxPtr dstBox,
    415     short src_w, short src_h, short drw_w, short drw_h,
    416     unsigned int flags, int overlayId, int pipeId)
    417 {
    418 #ifndef BAYTRAIL
    419     INIT_DRIVER_DATA;
    420     unsigned int        swidth, swidthy, swidthuv;
    421     unsigned int        mask, shift, offsety, offsetu;
    422     int                 tmp;
    423     uint32_t            OCMD;
    424     Bool                scaleChanged = FALSE;
    425     unsigned int        offset = wsbmBOOffsetHint(pPriv->wsbo[overlayId]) & 0x0FFFFFFF;
    426     I830OverlayRegPtr   overlay = (I830OverlayRegPtr)(pPriv->regmap[overlayId]);
    427     struct drm_psb_register_rw_arg regs;
    428     int i32EnableIEP = 0;
    429     int i32EnableIEPBLE = 0;
    430 
    431     /*before enabling overlay, make sure overlay is disabled first.*/
    432     if ((overlayId == OVERLAY_A) && !pPriv->overlayA_enabled) {
    433         memset(&regs, 0, sizeof(regs));
    434         regs.overlay_read_mask = OV_REGRWBITS_OVADD;
    435         drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, &regs, sizeof(regs));
    436 
    437         overlay->OCMD &= ~OVERLAY_ENABLE;
    438         regs.overlay_read_mask = 0;
    439         regs.overlay_write_mask = OV_REGRWBITS_OVADD;
    440         drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, &regs, sizeof(regs));
    441     }
    442 
    443     /* FIXME: don't know who and why add this
    444      *        comment it for full screen scale issue
    445      *        any concern contact qiang.miao (at) intel.com
    446      */
    447 #if 0
    448     if (drw_w >= 800) {
    449         x2 = x2 / 4;
    450         y2 = y2 / 4;
    451         dstBox->x2 = dstBox->x2 / 4;
    452         dstBox->y2 = dstBox->y2 / 4;
    453         drw_w = drw_w / 4;
    454         drw_h = drw_h / 4;
    455     }
    456 #endif
    457 
    458 #if USE_DCLRK
    459     overlay->DCLRKM &= ~CONST_ALPHA_ENABLE;
    460     if (pPriv->subpicture_enabled)
    461         overlay->DCLRKM &= ~DEST_KEY_ENABLE;
    462     else
    463         overlay->DCLRKM |= DEST_KEY_ENABLE;
    464     overlay->DCLRKV = pPriv->colorKey;
    465     overlay->DCLRKM |= 0xffffff;
    466 #else
    467     /* disable overlay destination color key didn't work,
    468     * it seems z-order of overlay has been bellow display pipe.
    469     */
    470     overlay->DCLRKM &= ~DEST_KEY_ENABLE;
    471 #endif
    472 
    473 #if USE_ROTATION_FUNC
    474     if (((pipeId == PIPEA) && (driver_data->mipi0_rotation != VA_ROTATION_NONE)) ||
    475         ((pipeId == PIPEB) && (driver_data->hdmi_rotation != VA_ROTATION_NONE))) {
    476         switch (pPriv->rotation) {
    477         case VA_ROTATION_NONE:
    478             break;
    479         case VA_ROTATION_270:
    480             tmp = dstBox->x1;
    481             dstBox->x1 = dstBox->y1;
    482             dstBox->y1 = pPriv->height_save - tmp;
    483             tmp = dstBox->x2;
    484             dstBox->x2 = dstBox->y2;
    485             dstBox->y2 = pPriv->height_save - tmp;
    486             tmp = dstBox->y1;
    487             dstBox->y1 = dstBox->y2;
    488             dstBox->y2 = tmp;
    489             tmp = drw_w;
    490             drw_w = drw_h;
    491             drw_h = tmp;
    492             break;
    493         case VA_ROTATION_180:
    494             tmp = dstBox->x1;
    495             dstBox->x1 = pPriv->width_save - dstBox->x2;
    496             dstBox->x2 = pPriv->width_save - tmp;
    497             tmp = dstBox->y1;
    498             dstBox->y1 = pPriv->height_save - dstBox->y2;
    499             dstBox->y2 = pPriv->height_save - tmp;
    500             break;
    501         case VA_ROTATION_90:
    502             tmp = dstBox->x1;
    503             dstBox->x1 = pPriv->width_save - dstBox->y1;
    504             dstBox->y1 = tmp;
    505             tmp = dstBox->x2;
    506             dstBox->x2 = pPriv->width_save - dstBox->y2;
    507             dstBox->y2 = tmp;
    508             tmp = dstBox->x1;
    509             dstBox->x1 = dstBox->x2;
    510             dstBox->x2 = tmp;
    511             tmp = drw_w;
    512             drw_w = drw_h;
    513             drw_h = tmp;
    514             break;
    515         }
    516     }
    517 #endif
    518 
    519     if (pPriv->oneLineMode) {
    520         /* change the coordinates with panel fitting active */
    521         dstBox->y1 = (((dstBox->y1 - 1) * pPriv->scaleRatio) >> 16) + 1;
    522         dstBox->y2 = ((dstBox->y2 * pPriv->scaleRatio) >> 16) + 1;
    523 
    524         /* Now, alter the height, so we scale to the correct size */
    525         drw_h = ((drw_h * pPriv->scaleRatio) >> 16) + 1;
    526     }
    527 
    528     shift = 6;
    529     mask = 0x3f;
    530 
    531     if (pPriv->curBuf == 0) {
    532         offsety = pPriv->YBuf0offset;
    533         offsetu = pPriv->UBuf0offset;
    534     } else {
    535         offsety = pPriv->YBuf1offset;
    536         offsetu = pPriv->UBuf1offset;
    537     }
    538 
    539     switch (id) {
    540     case VA_FOURCC_NV12:
    541         overlay->SWIDTH = width | ((width / 2 & 0x7ff) << 16);
    542         swidthy = i830_swidth(offsety, width, mask, shift);
    543         swidthuv = i830_swidth(offsetu, width / 2, mask, shift);
    544         overlay->SWIDTHSW = (swidthy) | (swidthuv << 16);
    545         overlay->SHEIGHT = height | ((height / 2) << 16);
    546         break;
    547     case VA_FOURCC_YV12:
    548     case VA_FOURCC_I420:
    549         overlay->SWIDTH = width | ((width / 2 & 0x7ff) << 16);
    550         swidthy  = i830_swidth(offsety, width, mask, shift);
    551         swidthuv = i830_swidth(offsetu, width / 2, mask, shift);
    552         overlay->SWIDTHSW = (swidthy) | (swidthuv << 16);
    553         overlay->SHEIGHT = height | ((height / 2) << 16);
    554         break;
    555     case VA_FOURCC_UYVY:
    556     case VA_FOURCC_YUY2:
    557     default:
    558         overlay->SWIDTH = width;
    559         swidth = ((offsety + (width << 1) + mask) >> shift) -
    560                  (offsety >> shift);
    561 
    562         swidth <<= 1;
    563         swidth -= 1;
    564         swidth <<= 2;
    565 
    566         overlay->SWIDTHSW = swidth;
    567         overlay->SHEIGHT = height;
    568         break;
    569     }
    570 
    571     overlay->DWINPOS = (dstBox->y1 << 16) | dstBox->x1;
    572 
    573     overlay->DWINSZ = (((dstBox->y2 - dstBox->y1) << 16) |
    574                        (dstBox->x2 - dstBox->x1));
    575 
    576     /* buffer locations */
    577     overlay->OBUF_0Y = pPriv->YBuf0offset;
    578     overlay->OBUF_0U = pPriv->UBuf0offset;
    579     overlay->OBUF_0V = pPriv->VBuf0offset;
    580     overlay->OBUF_1Y = pPriv->YBuf1offset;
    581     overlay->OBUF_1U = pPriv->UBuf1offset;
    582     overlay->OBUF_1V = pPriv->VBuf1offset;
    583 
    584     /*
    585      * Calculate horizontal and vertical scaling factors and polyphase
    586      * coefficients.
    587      */
    588 
    589     if (1) {
    590         int xscaleInt, xscaleFract, yscaleInt, yscaleFract;
    591         int xscaleIntUV, xscaleFractUV;
    592         int yscaleIntUV, yscaleFractUV;
    593         /* UV is half the size of Y -- YUV420 */
    594         int uvratio = 2;
    595         uint32_t newval;
    596         coeffRec xcoeffY[N_HORIZ_Y_TAPS * N_PHASES];
    597         coeffRec xcoeffUV[N_HORIZ_UV_TAPS * N_PHASES];
    598         int i, j, pos;
    599         int deinterlace_factor;
    600 
    601         /*
    602          * Y down-scale factor as a multiple of 4096.
    603          */
    604         if ((id == VA_FOURCC_NV12) && (0 != (flags & (VA_TOP_FIELD | VA_BOTTOM_FIELD))))
    605             deinterlace_factor = 2;
    606         else
    607             deinterlace_factor = 1;
    608 
    609         /* deinterlace requires twice of VSCALE setting*/
    610         if (src_w == drw_w && src_h == drw_h) {
    611             xscaleFract = 1 << 12;
    612             yscaleFract = (1 << 12) / deinterlace_factor;
    613         } else {
    614             xscaleFract = ((src_w - 1) << 12) / drw_w;
    615             yscaleFract = ((src_h - 1) << 12) / (deinterlace_factor * drw_h);
    616         }
    617 
    618         /* Calculate the UV scaling factor. */
    619         xscaleFractUV = xscaleFract / uvratio;
    620         yscaleFractUV = yscaleFract / uvratio;
    621 
    622         /*
    623          * To keep the relative Y and UV ratios exact, round the Y scales
    624          * to a multiple of the Y/UV ratio.
    625          */
    626         xscaleFract = xscaleFractUV * uvratio;
    627         yscaleFract = yscaleFractUV * uvratio;
    628 
    629         /* Integer (un-multiplied) values. */
    630         xscaleInt = xscaleFract >> 12;
    631         yscaleInt = yscaleFract >> 12;
    632 
    633         xscaleIntUV = xscaleFractUV >> 12;
    634         yscaleIntUV = yscaleFractUV >> 12;
    635 
    636         /* shouldn't get here */
    637         if (xscaleInt > 7) {
    638             return;
    639         }
    640 
    641         /* shouldn't get here */
    642         if (xscaleIntUV > 7) {
    643             return;
    644         }
    645 
    646         if (pPriv->is_mfld)
    647             newval = (xscaleInt << 15) |
    648                      ((xscaleFract & 0xFFF) << 3) | ((yscaleFract & 0xFFF) << 20);
    649         else
    650             newval = (xscaleInt << 16) |
    651                      ((xscaleFract & 0xFFF) << 3) | ((yscaleFract & 0xFFF) << 20);
    652 
    653         if (newval != overlay->YRGBSCALE) {
    654             scaleChanged = TRUE;
    655             overlay->YRGBSCALE = newval;
    656         }
    657 
    658         if (pPriv->is_mfld)
    659             newval = (xscaleIntUV << 15) | ((xscaleFractUV & 0xFFF) << 3) |
    660                      ((yscaleFractUV & 0xFFF) << 20);
    661         else
    662             newval = (xscaleIntUV << 16) | ((xscaleFractUV & 0xFFF) << 3) |
    663                      ((yscaleFractUV & 0xFFF) << 20);
    664 
    665         if (newval != overlay->UVSCALE) {
    666             scaleChanged = TRUE;
    667             overlay->UVSCALE = newval;
    668         }
    669 
    670         newval = yscaleInt << 16 | yscaleIntUV;
    671         if (newval != overlay->UVSCALEV) {
    672             scaleChanged = TRUE;
    673             overlay->UVSCALEV = newval;
    674         }
    675 
    676         /* Recalculate coefficients if the scaling changed. */
    677 
    678         /*
    679          * Only Horizontal coefficients so far.
    680          */
    681         if (scaleChanged) {
    682             double fCutoffY;
    683             double fCutoffUV;
    684 
    685             fCutoffY = xscaleFract / 4096.0;
    686             fCutoffUV = xscaleFractUV / 4096.0;
    687 
    688             /* Limit to between 1.0 and 3.0. */
    689             if (fCutoffY < MIN_CUTOFF_FREQ)
    690                 fCutoffY = MIN_CUTOFF_FREQ;
    691             if (fCutoffY > MAX_CUTOFF_FREQ)
    692                 fCutoffY = MAX_CUTOFF_FREQ;
    693             if (fCutoffUV < MIN_CUTOFF_FREQ)
    694                 fCutoffUV = MIN_CUTOFF_FREQ;
    695             if (fCutoffUV > MAX_CUTOFF_FREQ)
    696                 fCutoffUV = MAX_CUTOFF_FREQ;
    697 
    698             UpdateCoeff(N_HORIZ_Y_TAPS, fCutoffY, TRUE, TRUE, xcoeffY);
    699             UpdateCoeff(N_HORIZ_UV_TAPS, fCutoffUV, TRUE, FALSE, xcoeffUV);
    700 
    701             for (i = 0; i < N_PHASES; i++) {
    702                 for (j = 0; j < N_HORIZ_Y_TAPS; j++) {
    703                     pos = i * N_HORIZ_Y_TAPS + j;
    704                     overlay->Y_HCOEFS[pos] = (xcoeffY[pos].sign << 15 |
    705                                               xcoeffY[pos].exponent << 12 |
    706                                               xcoeffY[pos].mantissa);
    707                 }
    708             }
    709             for (i = 0; i < N_PHASES; i++) {
    710                 for (j = 0; j < N_HORIZ_UV_TAPS; j++) {
    711                     pos = i * N_HORIZ_UV_TAPS + j;
    712                     overlay->UV_HCOEFS[pos] = (xcoeffUV[pos].sign << 15 |
    713                                                xcoeffUV[pos].exponent << 12 |
    714                                                xcoeffUV[pos].mantissa);
    715                 }
    716             }
    717         }
    718     }
    719 
    720     OCMD = OVERLAY_ENABLE;
    721 
    722     switch (id) {
    723     case VA_FOURCC_NV12:
    724         overlay->OSTRIDE = dstPitch | (dstPitch << 16);
    725         OCMD &= ~SOURCE_FORMAT;
    726         OCMD &= ~OV_BYTE_ORDER;
    727         OCMD |= NV12;//in the spec, there are two NV12, which to use?
    728         break;
    729     case VA_FOURCC_YV12:
    730     case VA_FOURCC_I420:
    731         /* set UV vertical phase to -0.25 */
    732         /* overlay->UV_VPH = 0x30003000; */
    733         overlay->OSTRIDE = (dstPitch * 2) | (dstPitch << 16);
    734         OCMD &= ~SOURCE_FORMAT;
    735         OCMD &= ~OV_BYTE_ORDER;
    736         OCMD |= YUV_420;
    737         break;
    738     case VA_FOURCC_UYVY:
    739     case VA_FOURCC_YUY2:
    740         overlay->OSTRIDE = dstPitch;
    741         OCMD &= ~SOURCE_FORMAT;
    742         OCMD |= YUV_422;
    743         OCMD &= ~OV_BYTE_ORDER;
    744         if (id == VA_FOURCC_UYVY)
    745             OCMD |= Y_SWAP;
    746         break;
    747     }
    748 
    749     if (flags & (VA_TOP_FIELD | VA_BOTTOM_FIELD)) {
    750         OCMD |= BUF_TYPE_FIELD;
    751         OCMD &= ~FIELD_SELECT;
    752 
    753         if (flags & VA_BOTTOM_FIELD) {
    754             OCMD |= FIELD1;
    755             overlay->OBUF_0Y = pPriv->YBuf0offset - srcPitch;
    756             overlay->OBUF_0U = pPriv->UBuf0offset - srcPitch;
    757             overlay->OBUF_0V = pPriv->VBuf0offset - srcPitch;
    758             overlay->OBUF_1Y = pPriv->YBuf1offset - srcPitch;
    759             overlay->OBUF_1U = pPriv->UBuf1offset - srcPitch;
    760             overlay->OBUF_1V = pPriv->VBuf1offset - srcPitch;
    761         } else
    762             OCMD |= FIELD0;
    763     } else {
    764         OCMD &= ~(FIELD_SELECT);
    765         OCMD &= ~BUF_TYPE_FIELD;
    766     }
    767 
    768     OCMD &= ~(BUFFER_SELECT);
    769 
    770     if (pPriv->curBuf == 0)
    771         OCMD |= BUFFER0;
    772     else
    773         OCMD |= BUFFER1;
    774 
    775     overlay->OCMD = OCMD;
    776 
    777     memset(&regs, 0, sizeof(regs));
    778     switch (overlayId) {
    779     case OVERLAY_A:
    780         pPriv->overlayA_enabled = 1;
    781         regs.overlay_write_mask = OV_REGRWBITS_OVADD;
    782         break;
    783     case OVERLAY_C:
    784         pPriv->overlayC_enabled = 1;
    785         regs.overlay_write_mask = OVC_REGRWBITS_OVADD;
    786         break;
    787     }
    788 
    789     if (pPriv->is_mfld) {
    790         i32EnableIEP = 0;
    791 
    792         i32EnableIEPBLE = 0;
    793 
    794         if (i32EnableIEP == 0) {
    795             overlay->OCONFIG = CC_OUT_8BIT;
    796             overlay->OCONFIG &= OVERLAY_C_PIPE_A | (~OVERLAY_C_PIPE_MASK);
    797             overlay->OCONFIG |= IEP_LITE_BYPASS;
    798             regs.overlay.OVADD = offset | 1;
    799             regs.overlay.IEP_ENABLED = 0;
    800             regs.overlay.buffer_handle = wsbmKBufHandle(wsbmKBuf(pPriv->wsbo[overlayId]));
    801         }
    802     } else {
    803         overlay->OCONFIG = CC_OUT_8BIT;
    804         overlay->OCONFIG |= IEP_LITE_BYPASS;
    805         regs.overlay.OVADD = offset | 1;
    806     }
    807 
    808     if (pPriv->is_mfld) {
    809         switch (pipeId) {
    810         case PIPEA:
    811             overlay->OCONFIG |= OVERLAY_C_PIPE_A;
    812             overlay->OCONFIG |= ZORDER_TOP;
    813             break;
    814         case PIPEB:
    815             overlay->OCONFIG |= OVERLAY_C_PIPE_B;
    816             overlay->OCONFIG |= ZORDER_TOP;
    817             regs.overlay.OVADD |= 0x80;
    818             break;
    819         case PIPEC:
    820             overlay->OCONFIG |= OVERLAY_C_PIPE_C;
    821             overlay->OCONFIG |= ZORDER_TOP;
    822             regs.overlay.OVADD |= 0x40;
    823             break;
    824         }
    825         overlay->OCONFIG |= ZORDER_TOP;
    826     } else
    827         overlay->OCONFIG |= pipeId << 18; /* mrst */
    828 
    829     if (IS_CTP(driver_data) || IS_MRFL(driver_data) )
    830         regs.overlay.b_wms = 1;
    831 
    832     drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, &regs, sizeof(regs));
    833 
    834     if (pPriv->is_mfld) {
    835         if (regs.overlay.IEP_ENABLED) {
    836 #if 0
    837             printf("regs.overlay BLE minmax 0x%x, BSSCC control 0x%x\n",
    838                    regs.overlay.IEP_BLE_MINMAX, regs.overlay.IEP_BSSCC_CONTROL);
    839 #endif
    840             *(unsigned int *)((unsigned int)&(overlay->IEP_SPACE[0]) + 0x804)  = regs.overlay.IEP_BLE_MINMAX;
    841         }
    842     }
    843 #endif
    844 }
    845 
    846 
    847 static void I830PutImageFlipRotateSurface(
    848     VADriverContextP ctx,
    849     object_surface_p obj_surface,
    850     int *src_w_new, int *src_h_new,
    851     int *width_new, int *height_new,
    852     psb_surface_p *psb_surface_new,
    853     int pipeId)
    854 {
    855     int src_w = *src_w_new, src_h =  *src_h_new;
    856     int width = *width_new, height = *height_new;
    857     int  tmp = 0;
    858 
    859     psb_surface_p psb_surface = NULL;
    860     INIT_DRIVER_DATA;
    861     PsbPortPrivPtr pPriv;
    862 
    863     /* local/extend display doesn't have render rotation */
    864     if (((pipeId == PIPEA) && (driver_data->local_rotation == VA_ROTATION_NONE)) ||
    865         ((pipeId == PIPEB) && (driver_data->extend_rotation == VA_ROTATION_NONE)))
    866         return;
    867 
    868     pPriv = (PsbPortPrivPtr)(&driver_data->coverlay_priv);
    869 
    870     if (pipeId == PIPEA) {
    871         if (driver_data->local_rotation != VA_ROTATION_NONE) {
    872             psb_surface = obj_surface->out_loop_surface;
    873             width = obj_surface->width_r;
    874             height = obj_surface->height_r;
    875             if (driver_data->local_rotation != VA_ROTATION_180) {
    876                 tmp = src_w;
    877                 src_w = src_h;
    878                 src_h = tmp;
    879             }
    880         }
    881         if ((driver_data->local_rotation == VA_ROTATION_NONE) ||
    882             (driver_data->local_rotation == VA_ROTATION_180)) {
    883             pPriv->width_save = pPriv->display_width;
    884             pPriv->height_save = pPriv->display_height;
    885         } else {
    886             pPriv->width_save = pPriv->display_height;
    887             pPriv->height_save = pPriv->display_width;
    888         }
    889         if (driver_data->is_android == 0)
    890             pPriv->rotation = driver_data->local_rotation;
    891         else
    892             pPriv->rotation = 0;
    893     } else if (pipeId == PIPEB) {
    894         if (driver_data->extend_rotation != VA_ROTATION_NONE) {
    895             psb_surface = obj_surface->out_loop_surface;
    896             width = obj_surface->width_r;
    897             height = obj_surface->height_r;
    898             if (driver_data->extend_rotation != VA_ROTATION_180) {
    899                 tmp = src_w;
    900                 src_w = src_h;
    901                 src_h = tmp;
    902             }
    903         }
    904         if ((driver_data->extend_rotation == VA_ROTATION_NONE) ||
    905             (driver_data->extend_rotation == VA_ROTATION_180)) {
    906             pPriv->width_save = pPriv->extend_display_width;
    907             pPriv->height_save = pPriv->extend_display_height;
    908         } else {
    909             pPriv->width_save = pPriv->extend_display_height;
    910             pPriv->height_save = pPriv->extend_display_width;
    911         }
    912         if (driver_data->is_android == 0)
    913             pPriv->rotation = driver_data->extend_rotation;
    914         else
    915             pPriv->rotation = 0;
    916     }
    917 
    918     *src_w_new = src_w;
    919     *src_h_new = src_h;
    920     *width_new = width;
    921     *height_new = height;
    922     *psb_surface_new = psb_surface;
    923 }
    924 
    925 
    926 static int I830PutImageFlipRotateDebug(
    927     VADriverContextP ctx,
    928     VASurfaceID surface,
    929     short __maybe_unused src_x, short __maybe_unused src_y,
    930     short __maybe_unused src_w, short __maybe_unused src_h,
    931     short __maybe_unused drw_x, short __maybe_unused drw_y,
    932     short __maybe_unused drw_w, short __maybe_unused drw_h,
    933     int __maybe_unused fourcc, int __maybe_unused flags,
    934     int __maybe_unused overlayId,
    935     int pipeId)
    936 {
    937     INIT_DRIVER_DATA;
    938     object_surface_p obj_surface;
    939     psb_surface_p psb_surface = NULL;
    940     VAStatus vaStatus = VA_STATUS_SUCCESS;
    941 
    942     obj_surface = SURFACE(surface);
    943     CHECK_SURFACE(obj_surface);
    944 
    945     if (pipeId != 0)
    946         return -1;
    947 
    948     psb_surface = obj_surface->out_loop_surface;
    949     psb_buffer_p buf = &psb_surface->buf;
    950     unsigned char *data, *chroma, *buffer, *header;
    951     static FILE *pf = NULL;
    952     int ret, i;
    953     if (!psb_surface)
    954         goto dump_out;
    955     if (pf == NULL)
    956         if ((pf = fopen("/home/dump.yuv", "w+")) == NULL) {
    957             printf("Open yuv file fails\n");
    958             return -1;
    959         }
    960     ret = psb_buffer_map(buf, &data);
    961 
    962     if (ret) {
    963         printf("Map buffer fail\n");
    964         return -1;
    965     }
    966     for (i = 0; i < obj_surface->height_r; i++) {
    967         fwrite(data, 1, obj_surface->width_r, pf);
    968         data += psb_surface->stride;
    969     }
    970 
    971     buffer = malloc(obj_surface->height_r * obj_surface->width_r);
    972     if (!buffer) {
    973         printf("Alloc chroma buffer fail\n");
    974         return -1;
    975     }
    976     header = buffer;
    977     chroma = data;
    978     for (i = 0; i < obj_surface->height_r / 2; i++) {
    979         int j;
    980         for (j = 0; j < obj_surface->width_r / 2; j++) {
    981             *buffer++ = data[j*2];
    982         }
    983         data += psb_surface->stride;
    984     }
    985 
    986     data = chroma;
    987     for (i = 0; i < obj_surface->height_r / 2; i++) {
    988         int j;
    989         for (j = 0; j < obj_surface->width_r / 2; j++) {
    990             *buffer++ = data[j*2 + 1];
    991         }
    992         data += psb_surface->stride;
    993     }
    994 
    995     fwrite(header, obj_surface->height_r / 2, obj_surface->width_r, pf);
    996     free(header);
    997     psb_buffer_unmap(buf);
    998     return 0;
    999 
   1000 dump_out:
   1001     return -1;
   1002 }
   1003 
   1004 
   1005 /*
   1006  * The source rectangle of the video is defined by (src_x, src_y, src_w, src_h).
   1007  * The dest rectangle of the video is defined by (drw_x, drw_y, drw_w, drw_h).
   1008  * id is a fourcc code for the format of the video.
   1009  * buf is the pointer to the source data in system memory.
   1010  * width and height are the w/h of the source data.
   1011  * If "sync" is TRUE, then we must be finished with *buf at the point of return
   1012  * (which we always are).
   1013  * clipBoxes is the clipping region in screen space.
   1014  * data is a pointer to our port private.
   1015  * pDraw is a Drawable, which might not be the screen in the case of
   1016  * compositing.  It's a new argument to the function in the 1.1 server.
   1017  */
   1018 static int I830PutImage(
   1019     VADriverContextP ctx,
   1020     VASurfaceID surface,
   1021     int src_x, int src_y,
   1022     int src_w, int src_h,
   1023     int drw_x, int drw_y,
   1024     int drw_w, int drw_h,
   1025     int fourcc, int flags,
   1026     int overlayId,
   1027     int pipeId)
   1028 {
   1029     INIT_DRIVER_DATA;
   1030     int x1, x2, y1, y2;
   1031     int width, height;
   1032     int top, left, npixels;
   1033     int pitch = 0, pitch2 = 0;
   1034     unsigned int pre_add;
   1035     unsigned int gtt_ofs;
   1036     struct _WsbmBufferObject *drm_buf;
   1037     BoxRec dstBox;
   1038     PsbPortPrivPtr pPriv;
   1039     object_surface_p obj_surface = SURFACE(surface);
   1040     psb_surface_p psb_surface = NULL;
   1041 
   1042     /* silent kw */
   1043     if (NULL == obj_surface)
   1044         return 1;
   1045 
   1046     pPriv = (PsbPortPrivPtr)(&driver_data->coverlay_priv);
   1047 
   1048     switch (fourcc) {
   1049     case VA_FOURCC_NV12:
   1050         width = obj_surface->width;
   1051         height = obj_surface->height;
   1052         break;
   1053     default:
   1054         width = obj_surface->width;
   1055         height = obj_surface->height;
   1056         break;
   1057     }
   1058 
   1059     /* rotate support here: more check?
   1060      * and for oold also?
   1061      */
   1062     psb_surface = obj_surface->psb_surface;
   1063     I830PutImageFlipRotateSurface(ctx, obj_surface,
   1064                                   &src_w, &src_h, &width, &height,
   1065                                   &psb_surface, pipeId);
   1066 
   1067     if (NULL == psb_surface) {
   1068         /*Rotate surface may not be ready, so we have to discard this frame.*/
   1069         drv_debug_msg(VIDEO_DEBUG_GENERAL, "Discard this frame if rotate surface hasn't be ready.\n");
   1070 
   1071         return 1;
   1072     }
   1073     width = (width <= 1920) ? width : 1920;
   1074 
   1075     /* If dst width and height are less than 1/8th the src size, the
   1076      * src/dst scale factor becomes larger than 8 and doesn't fit in
   1077      * the scale register.
   1078      */
   1079     if (src_w >= (drw_w * 8))
   1080         drw_w = src_w / 7;
   1081 
   1082     if (src_h >= (drw_h * 8))
   1083         drw_h = src_h / 7;
   1084 
   1085     /* Clip */
   1086     x1 = src_x;
   1087     x2 = src_x + src_w;
   1088     y1 = src_y;
   1089     y2 = src_y + src_h;
   1090 
   1091     dstBox.x1 = drw_x;
   1092     dstBox.x2 = drw_x + drw_w;
   1093     dstBox.y1 = drw_y;
   1094     dstBox.y2 = drw_y + drw_h;
   1095 
   1096 #if USE_CLIP_FUNC
   1097     if (!i830_get_crtc(pScrn, &crtc, &dstBox))
   1098         return Success;
   1099 
   1100     /*
   1101      *Update drw_* and 'clipBoxes' according to current downscale/upscale state
   1102      * Make sure the area determined by drw_* is in 'clipBoxes'
   1103      */
   1104     if (crtc->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
   1105         h_ratio = (float)pScrn->pScreen->height / pPriv->width_save;
   1106         v_ratio = (float)pScrn->pScreen->width / pPriv->height_save;
   1107     } else {
   1108         h_ratio = (float)pScrn->pScreen->width / pPriv->width_save;
   1109         v_ratio = (float)pScrn->pScreen->height / pPriv->height_save;
   1110     }
   1111 
   1112     /* Horizontal downscale/upscale */
   1113     if ((int)h_ratio)
   1114         clipBoxes->extents.x1 /= h_ratio;
   1115     else if (!(int)h_ratio)
   1116         clipBoxes->extents.x2 /= h_ratio;
   1117 
   1118     /* Vertical downscale/upscale */
   1119     if ((int)v_ratio)
   1120         clipBoxes->extents.y1 /= v_ratio;
   1121     else if (!(int)v_ratio)
   1122         clipBoxes->extents.y2 /= v_ratio;
   1123 
   1124     drw_x /= h_ratio;
   1125     drw_y /= v_ratio;
   1126     drw_w /= h_ratio;
   1127     drw_h /= v_ratio;
   1128 
   1129     dstBox.x1 = drw_x;
   1130     dstBox.x2 = drw_x + drw_w;
   1131     dstBox.y1 = drw_y;
   1132     dstBox.y2 = drw_y + drw_h;
   1133 
   1134     /* Count in client supplied clipboxes */
   1135     clipRegion = clipBoxes;
   1136     psb_perform_clip(pScrn, vaPtr->clipbox, vaPtr->num_clipbox, clipBoxes, clipRegion, pDraw);
   1137 
   1138     if (!i830_clip_video_helper(pScrn,
   1139                                 &crtc,
   1140                                 &dstBox, &x1, &x2, &y1, &y2, clipRegion,
   1141                                 width, height)) {
   1142         xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "%s: Fail to clip video to any crtc!\n", __FUNCTION__);
   1143         return 0;
   1144     }
   1145 #endif
   1146 
   1147     switch (fourcc) {
   1148     case VA_FOURCC_NV12:
   1149         pitch = (width + 0x3) & ~0x3;
   1150         pitch2 = psb_surface->stride;
   1151         break;
   1152     case VA_FOURCC_YV12:
   1153     case VA_FOURCC_I420:
   1154         pitch = (width + 0x3) & ~0x3;
   1155         break;
   1156 #if USE_DISPLAY_C_SPRITE
   1157     case FOURCC_RGBA:
   1158         pitch = width << 2;
   1159         break;
   1160 #endif
   1161     case VA_FOURCC_UYVY:
   1162     case VA_FOURCC_YUY2:
   1163     default:
   1164         pitch = width << 1;
   1165         break;
   1166     }
   1167 
   1168     top = (y1) & ~1;
   1169     left = (x1) & ~1;
   1170     npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left;
   1171 
   1172     if (fourcc == VA_FOURCC_NV12) {
   1173         pre_add = psb_surface->buf.buffer_ofs;
   1174         drm_buf = psb_surface->buf.drm_buf;
   1175         gtt_ofs = wsbmBOOffsetHint(drm_buf) & 0x0FFFFFFF;
   1176 
   1177         /*skip pad bytes.*/
   1178         if (driver_data->local_rotation == VA_ROTATION_90) {
   1179             left += ((src_w + 0xf) & ~0xf) - src_w;
   1180         } else if (driver_data->local_rotation == VA_ROTATION_270) {
   1181             top += ((src_h + 0xf) & ~0xf) - src_h;
   1182         } else if (driver_data->local_rotation == VA_ROTATION_180) {
   1183             left += ((src_w + 0xf) & ~0xf) - src_w;
   1184             top += ((src_h + 0xf) & ~0xf) - src_h;
   1185         }
   1186         pPriv->YBuf0offset = pre_add + gtt_ofs  + top * pitch2 + left;
   1187         pPriv->YBuf1offset = pPriv->YBuf0offset;
   1188         pPriv->UBuf0offset = pre_add + gtt_ofs + (pitch2  * height) + top * (pitch2 / 2) + left;
   1189         pPriv->VBuf0offset = pPriv->UBuf0offset;
   1190         pPriv->UBuf1offset = pPriv->UBuf0offset;
   1191         pPriv->VBuf1offset = pPriv->UBuf0offset;
   1192     } else {
   1193         //TBD
   1194         //pPriv->YBuf0offset = pPriv->videoBuf0_gtt_offset << PAGE_SHIFT;
   1195         //pPriv->YBuf1offset = pPriv->videoBuf1_gtt_offset << PAGE_SHIFT;
   1196         if (pPriv->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
   1197             pPriv->UBuf0offset = pPriv->YBuf0offset + (pitch2  * width);
   1198             pPriv->VBuf0offset = pPriv->UBuf0offset + (pitch2 * width / 2);
   1199             pPriv->UBuf1offset = pPriv->YBuf1offset + (pitch2 * width);
   1200             pPriv->VBuf1offset = pPriv->UBuf1offset + (pitch2 * width / 2);
   1201         } else {
   1202             pPriv->UBuf0offset = pPriv->YBuf0offset + (pitch2 * height);
   1203             pPriv->VBuf0offset = pPriv->UBuf0offset + (pitch2 * height / 2);
   1204             pPriv->UBuf1offset = pPriv->YBuf1offset + (pitch2 * height);
   1205             pPriv->VBuf1offset = pPriv->UBuf1offset + (pitch2 * height / 2);
   1206         }
   1207     }
   1208 
   1209 #if USE_DISPLAY_C_SPRITE
   1210     if (fourcc == FOURCC_RGBA   \
   1211         || (fourcc == FOURCC_XVVA   \
   1212             && (pPriv->rotation != RR_Rotate_0) \
   1213             && (vaPtr->dst_srf.fourcc == VA_FOURCC_RGBA)))
   1214         i830_display_video_sprite(pScrn, crtc, width, height, dstPitch,
   1215                                   &dstBox, sprite_offset);
   1216     else
   1217 #endif
   1218         i830_display_video(ctx, pPriv, surface, fourcc, src_w, src_h, pitch2, pitch,
   1219                            x1, y1, x2, y2, &dstBox, src_w, src_h,
   1220                            drw_w, drw_h, flags, overlayId, pipeId);
   1221 
   1222     // FIXME : do I use two buffers here really?
   1223     //    pPriv->curBuf = (pPriv->curBuf + 1) & 1;
   1224 
   1225     return Success;
   1226 }
   1227 
   1228 
   1229 
   1230 static void psbPortPrivCreate(PsbPortPrivPtr pPriv)
   1231 {
   1232 #if 0
   1233     REGION_NULL(pScreen, &pPriv->clip);
   1234 #endif
   1235 
   1236     /* coeffs defaut value */
   1237     pPriv->brightness.Value = OV_BRIGHTNESS_DEFAULT_VALUE;
   1238     pPriv->brightness.Fraction = 0;
   1239 
   1240     pPriv->contrast.Value = OV_CONTRAST_DEFAULT_VALUE;
   1241     pPriv->contrast.Fraction = 0;
   1242 
   1243     pPriv->hue.Value = OV_HUE_DEFAULT_VALUE;
   1244     pPriv->hue.Fraction = 0;
   1245 
   1246     pPriv->saturation.Value = OV_SATURATION_DEFAULT_VALUE;
   1247     pPriv->saturation.Fraction = 0;
   1248     pPriv->subpicture_enabled = 0;
   1249     pPriv->subpicture_enable_mask = 0;
   1250     pPriv->overlayA_enabled = 0;
   1251     pPriv->overlayC_enabled = 0;
   1252     pPriv->overlayA_pipeId = PIPEA;
   1253     pPriv->overlayC_pipeId = PIPEB;
   1254 
   1255     /* FIXME: is this right? set up to current screen size */
   1256 #if 1
   1257     pPriv->width_save = 1024;
   1258     pPriv->height_save = 600;
   1259 #endif
   1260 }
   1261 
   1262 static void
   1263 psbPortPrivDestroy(VADriverContextP ctx, PsbPortPrivPtr pPriv)
   1264 {
   1265     I830StopVideo(ctx);
   1266 
   1267     wsbmBOUnmap(pPriv->wsbo[0]);
   1268     wsbmBOUnreference(&pPriv->wsbo[0]);
   1269     wsbmBOUnmap(pPriv->wsbo[1]);
   1270     wsbmBOUnreference(&pPriv->wsbo[1]);
   1271     if (pPriv->is_mfld) {
   1272         if (pPriv->p_iep_lite_context)
   1273             free(pPriv->p_iep_lite_context);
   1274     }
   1275     pPriv->p_iep_lite_context = NULL;
   1276 }
   1277 
   1278 static int
   1279 psbSetupImageVideoOverlay(VADriverContextP ctx, PsbPortPrivPtr pPriv)
   1280 {
   1281     INIT_DRIVER_DATA;
   1282     I830OverlayRegPtr overlayA = NULL;
   1283     I830OverlayRegPtr overlayC = NULL;
   1284     int ret;
   1285     psbPortPrivCreate(pPriv);
   1286 
   1287 
   1288     /* use green as color key by default for android media player */
   1289     pPriv->colorKey = driver_data->color_key/*0x0440*/;
   1290 
   1291     /*Bypass color correction. Because these color
   1292     correction can be done in pipe color correction in future.*/
   1293     pPriv->brightness.Value = 0;   /*-19*/
   1294     pPriv->contrast.Value = 0x40;  /*75*/
   1295     pPriv->saturation.Value = 0x80;  /*146*/
   1296 
   1297     pPriv->gamma5 = 0xc0c0c0;
   1298     pPriv->gamma4 = 0x808080;
   1299     pPriv->gamma3 = 0x404040;
   1300     pPriv->gamma2 = 0x202020;
   1301     pPriv->gamma1 = 0x101010;
   1302     pPriv->gamma0 = 0x080808;
   1303 
   1304     pPriv->rotation = VA_ROTATION_NONE;
   1305     pPriv->subpic_clear_flag = 1;
   1306 #if 0
   1307     /* gotta uninit this someplace */
   1308     REGION_NULL(pScreen, &pPriv->clip);
   1309 #endif
   1310 
   1311     /* With LFP's we need to detect whether we're in One Line Mode, which
   1312      * essentially means a resolution greater than 1024x768, and fix up
   1313      * the scaler accordingly.
   1314      */
   1315     pPriv->scaleRatio = 0x10000;
   1316     pPriv->oneLineMode = FALSE;
   1317 
   1318     ret = wsbmGenBuffers(driver_data->main_pool, 2,
   1319                          &pPriv->wsbo[0], 64 * 1024, /* 64k alignment */
   1320                          WSBM_PL_FLAG_TT);
   1321     if (ret)
   1322         goto out_err;
   1323 
   1324     ret = wsbmBOData(pPriv->wsbo[0],
   1325                      5 * 4096,
   1326                      NULL, NULL,
   1327                      WSBM_PL_FLAG_TT);
   1328     if (ret)
   1329         goto out_err_bo0;
   1330 
   1331     pPriv->regmap[0] = wsbmBOMap(pPriv->wsbo[0], WSBM_ACCESS_READ | WSBM_ACCESS_WRITE);
   1332     if (!pPriv->regmap[0]) {
   1333         goto out_err_bo0;
   1334     }
   1335 
   1336     ret = wsbmBOData(pPriv->wsbo[1],
   1337                      5 * 4096,
   1338                      NULL, NULL,
   1339                      WSBM_PL_FLAG_TT);
   1340     if (ret)
   1341         goto out_err_bo1;
   1342 
   1343     pPriv->regmap[1] = wsbmBOMap(pPriv->wsbo[1], WSBM_ACCESS_READ | WSBM_ACCESS_WRITE);
   1344     if (!pPriv->regmap[1]) {
   1345         goto out_err_bo1;
   1346     }
   1347 
   1348     overlayA = (I830OverlayRegPtr)(pPriv->regmap[0]);
   1349     overlayC = (I830OverlayRegPtr)(pPriv->regmap[1]);
   1350 
   1351     if (pPriv->is_mfld) {
   1352         driver_data->ble_black_mode.value = 1;
   1353         driver_data->ble_white_mode.value = 3;
   1354         driver_data->blueStretch_gain.value = 200;
   1355         driver_data->skinColorCorrection_gain.value = 100;
   1356         driver_data->hue.value = (5.25f * (1 << 25));
   1357         driver_data->saturation.value = (1.07f * (1 << 25));
   1358         driver_data->brightness.value = (-10.1f * (1 << 10));
   1359         driver_data->contrast.value = (0.99f * (1 << 25));
   1360     }
   1361 
   1362     return 0;
   1363 
   1364 out_err_bo1:
   1365     wsbmBOUnreference(&pPriv->wsbo[1]);
   1366 out_err_bo0:
   1367     wsbmBOUnreference(&pPriv->wsbo[0]);
   1368 
   1369 out_err:
   1370     return -1;
   1371 }
   1372 
   1373 int psb_coverlay_init(VADriverContextP ctx)
   1374 {
   1375 #ifndef BAYTRAIL
   1376     INIT_DRIVER_DATA;
   1377     PsbPortPrivPtr pPriv = &driver_data->coverlay_priv;
   1378     struct drm_psb_register_rw_arg regs;
   1379     int ret;
   1380 
   1381     memset(pPriv, 0, sizeof(PsbPortPrivRec));
   1382     pPriv->is_mfld = (IS_MFLD(driver_data) || IS_MRFL(driver_data));
   1383 
   1384     ret = psbSetupImageVideoOverlay(ctx, pPriv);
   1385     if (ret != 0) {
   1386         drv_debug_msg(VIDEO_DEBUG_ERROR, "psb_coverlay_init : Create overlay cmd buffer failed.\n");
   1387         return -1;
   1388     }
   1389 
   1390     if (pPriv->is_mfld && driver_data->is_android) {
   1391         drv_debug_msg(VIDEO_DEBUG_GENERAL, "Android ExtVideo: set PIPEB(HDMI)display plane on the bottom.\n");
   1392 
   1393         memset(&regs, 0, sizeof(regs));
   1394         regs.display_read_mask = REGRWBITS_DSPBCNTR;
   1395         drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, &regs, sizeof(regs));
   1396         regs.display.dspcntr_b |= DISPPLANE_BOTTOM;
   1397         regs.display_write_mask = REGRWBITS_DSPBCNTR;
   1398         drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, &regs, sizeof(regs));
   1399     }
   1400 
   1401     I830ResetVideo(ctx, pPriv);
   1402     I830UpdateGamma(ctx, pPriv);
   1403 #endif
   1404     return 0;
   1405 }
   1406 
   1407 int psb_coverlay_stop(VADriverContextP ctx)
   1408 {
   1409     I830StopVideo(ctx);
   1410     return 0;
   1411 }
   1412 
   1413 int psb_coverlay_deinit(VADriverContextP ctx)
   1414 {
   1415 #ifndef BAYTRAIL
   1416     INIT_DRIVER_DATA;
   1417     PsbPortPrivPtr pPriv = &driver_data->coverlay_priv;
   1418     struct drm_psb_register_rw_arg regs;
   1419 
   1420     if (pPriv->is_mfld && driver_data->is_android) {
   1421         drv_debug_msg(VIDEO_DEBUG_GENERAL, "Android ExtVideo: set PIPEB(HDMI)display plane normal.\n");
   1422 
   1423         memset(&regs, 0, sizeof(regs));
   1424         regs.display_read_mask = REGRWBITS_DSPBCNTR;
   1425         drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, &regs, sizeof(regs));
   1426         regs.display.dspcntr_b &= ~DISPPLANE_BOTTOM;
   1427         regs.display_write_mask = REGRWBITS_DSPBCNTR;
   1428         drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, &regs, sizeof(regs));
   1429     }
   1430 
   1431     psbPortPrivDestroy(ctx, pPriv);
   1432 #endif
   1433     return 0;
   1434 }
   1435 
   1436 VAStatus psb_putsurface_overlay(
   1437     VADriverContextP ctx,
   1438     VASurfaceID surface,
   1439     short srcx,
   1440     short srcy,
   1441     unsigned short srcw,
   1442     unsigned short srch,
   1443     short destx,
   1444     short desty,
   1445     unsigned short destw,
   1446     unsigned short desth,
   1447     unsigned int flags, /* de-interlacing flags */
   1448     int overlayId,
   1449     int pipeId
   1450 )
   1451 {
   1452     INIT_DRIVER_DATA;
   1453     object_surface_p obj_surface = SURFACE(surface);
   1454     PsbPortPrivPtr pPriv = (PsbPortPrivPtr)(&driver_data->coverlay_priv);
   1455 #if 0
   1456     if ((overlayId == OVERLAY_A) && (pPriv->overlayA_pipeId != pipeId)) {
   1457         pPriv->overlayA_pipeId = pipeId;
   1458         I830SwitchPipe(ctx, OVERLAY_A, pipeId);
   1459         drv_debug_msg(VIDEO_DEBUG_GENERAL, "OverlayA switch pipe to %d, stop overlayA first.\n", pipeId);
   1460     } else if ((overlayId == OVERLAY_C) && (pPriv->overlayC_pipeId != pipeId)) {
   1461         pPriv->overlayC_pipeId = pipeId;
   1462         I830SwitchPipe(ctx, OVERLAY_C, pipeId);
   1463         drv_debug_msg(VIDEO_DEBUG_GENERAL, "OverlayC switch pipe to %d, stop overlayC first.\n", pipeId);
   1464     }
   1465 #endif
   1466     I830PutImage(ctx, surface, srcx, srcy, srcw, srch,
   1467                  destx, desty, destw, desth,
   1468                  VA_FOURCC_NV12, flags, overlayId, pipeId);
   1469 
   1470     /* current surface is being displayed */
   1471     if (driver_data->cur_displaying_surface != VA_INVALID_SURFACE)
   1472         driver_data->last_displaying_surface = driver_data->cur_displaying_surface;
   1473 
   1474     if (obj_surface == NULL) {
   1475         drv_debug_msg(VIDEO_DEBUG_ERROR, "Invalid surface ID: 0x%08x\n", surface);
   1476         return VA_STATUS_ERROR_INVALID_SURFACE;
   1477     }
   1478 
   1479     obj_surface->display_timestamp = GetTickCount();
   1480     driver_data->cur_displaying_surface = surface;
   1481 
   1482     return VA_STATUS_SUCCESS;
   1483 }
   1484