Home | History | Annotate | Download | only in mrst
      1 /*
      2  * Copyright (c) 2011 Intel Corporation. All Rights Reserved.
      3  * Copyright (c) Imagination Technologies Limited, UK
      4  *
      5  * Permission is hereby granted, free of charge, to any person obtaining a
      6  * copy of this software and associated documentation files (the
      7  * "Software"), to deal in the Software without restriction, including
      8  * without limitation the rights to use, copy, modify, merge, publish,
      9  * distribute, sub license, and/or sell copies of the Software, and to
     10  * permit persons to whom the Software is furnished to do so, subject to
     11  * the following conditions:
     12  *
     13  * The above copyright notice and this permission notice (including the
     14  * next paragraph) shall be included in all copies or substantial portions
     15  * of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
     20  * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
     21  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     22  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     23  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     24  *
     25  * Authors:
     26  *    Shengquan Yuan  <shengquan.yuan (at) intel.com>
     27  *
     28  */
     29 
     30 #include "psb_MPEG2.h"
     31 #include "psb_def.h"
     32 #include "psb_surface.h"
     33 #include "psb_cmdbuf.h"
     34 #include "psb_drv_debug.h"
     35 
     36 #include "hwdefs/reg_io2.h"
     37 #include "hwdefs/msvdx_offsets.h"
     38 #include "hwdefs/msvdx_cmds_io2.h"
     39 #include "hwdefs/msvdx_vdmc_reg_io2.h"
     40 #include "hwdefs/msvdx_vec_reg_io2.h"
     41 #include "hwdefs/msvdx_vec_mpeg2_reg_io2.h"
     42 #include "hwdefs/dxva_fw_ctrl.h"
     43 
     44 #include <stdlib.h>
     45 #include <stdint.h>
     46 #include <string.h>
     47 
     48 
     49 /* TODO: for interlace
     50  * bit 0: first vector forward
     51  * bit 1: first vector backward
     52  * bit 2: second vector forward
     53  * bit 3: second vector backward
     54  */
     55 #define MBPARAM_MvertFieldSel_3(ptr)    (((ptr)->motion_vertical_field_select & 0x8) >> 3)
     56 #define MBPARAM_MvertFieldSel_2(ptr)    (((ptr)->motion_vertical_field_select & 0x4) >> 2)
     57 #define MBPARAM_MvertFieldSel_1(ptr)    (((ptr)->motion_vertical_field_select & 0x2) >> 1)
     58 #define MBPARAM_MvertFieldSel_0(ptr)    (((ptr)->motion_vertical_field_select & 0x1) >> 0)
     59 #define MBPARAM_MotionType(ptr)         (((ptr)->macroblock_modes.bits.frame_motion_type << 1) | (ptr)->macroblock_modes.bits.field_motion_type)
     60 #define MBPARAM_MotionBackward(ptr)     (((ptr)->macroblock_type & VA_MB_TYPE_MOTION_BACKWARD)?1:0)
     61 #define MBPARAM_MotionForward(ptr)      (((ptr)->macroblock_type & VA_MB_TYPE_MOTION_FORWARD)?1:0)
     62 #define MBPARAM_IntraMacroblock(ptr)    ((ptr)->macroblock_type & VA_MB_TYPE_MOTION_INTRA )
     63 #define MBPARAM_CodedBlockPattern(ptr)  ((ptr)->coded_block_pattern << 6) /* align with VA code */
     64 #define MBPARAM_MBskipsFollowing(ptr)   ((ptr)->num_skipped_macroblocks)
     65 
     66 typedef enum { MB_CODE_TYPE_I , MB_CODE_TYPE_P , MB_CODE_TYPE_B , MB_CODE_TYPE_GMC } eMB_CODE_TYPE;
     67 
     68 /* Constants */
     69 #define PICTURE_CODING_I                0x01
     70 #define PICTURE_CODING_P                0x02
     71 #define PICTURE_CODING_B                0x03
     72 
     73 #define CODEC_MODE_MPEG2                3
     74 #define CODEC_PROFILE_MPEG2_MAIN        1
     75 
     76 /* picture structure */
     77 #define TOP_FIELD                       1
     78 #define BOTTOM_FIELD                    2
     79 #define FRAME_PICTURE                   3
     80 
     81 #define INTRA_MB_WORST_CASE             6
     82 #define INTER_MB_WORST_CASE             100
     83 
     84 static  const uint32_t  pict_libva2msvdx[] = {0,/* Invalid picture type */
     85         0,/* I picture */
     86         1,/* P picture */
     87         2,/* B pricture */
     88         3
     89                                              };/* Invalid picture type */
     90 
     91 
     92 static  const uint32_t  ft_libva2msvdx[] = {0,/* Invalid picture type   */
     93         0,/* Top field */
     94         1,/* Bottom field */
     95         2
     96                                            };/* Frame picture     */
     97 
     98 
     99 struct context_MPEG2MC_s {
    100     object_context_p obj_context; /* back reference */
    101 
    102     VAMacroblockParameterBufferMPEG2 *mb_param ;        /* Pointer to the mbCtrl structure */
    103     uint32_t mb_in_buffer;  /* Number of MBs in current buffer */
    104     uint32_t mb_first_addr; /* MB address of first mb in buffer */
    105 
    106     uint32_t picture_coding_type;
    107     uint32_t picture_structure;
    108 
    109     uint32_t coded_picture_width;
    110     uint32_t coded_picture_height;
    111 
    112     uint32_t picture_width_mb; /* in macroblocks */
    113     uint32_t picture_height_mb; /* in macroblocks */
    114     uint32_t size_mb; /* in macroblocks */
    115 
    116     VAPictureParameterBufferMPEG2 *pic_params;
    117 
    118     object_surface_p forward_ref_surface;
    119     object_surface_p backward_ref_surface;
    120 
    121     uint32_t ref_indexA;
    122     uint32_t ref_indexB;
    123 
    124     uint32_t coded_picture_size;
    125     uint32_t display_picture_size;
    126     uint32_t operation_mode;
    127 
    128     uint32_t *lldma_idx; /* Index in command stream for LLDMA pointer */
    129     uint32_t residual_pendingDMA;
    130     IMG_INT32   residual_sent;
    131 
    132     psb_buffer_p residual_buf;
    133     uint32_t blk_in_buffer;/* buffer elements */
    134     uint32_t blk_size;/* buffer elements size */
    135 
    136     uint32_t fstmb_slice;
    137 };
    138 
    139 typedef struct context_MPEG2MC_s *context_MPEG2MC_p;
    140 
    141 #define INIT_CONTEXT_MPEG2MC    context_MPEG2MC_p ctx = (context_MPEG2MC_p) obj_context->format_data
    142 #define SURFACE(id)     ((object_surface_p) object_heap_lookup( &ctx->obj_context->driver_data->surface_heap, id ))
    143 
    144 static void     psb__MPEG2MC_send_interPB_prediction(
    145     context_MPEG2MC_p ctx,
    146     psb_cmdbuf_p const  cmdbuf,
    147     VAMacroblockParameterBufferMPEG2 * const    mb_param,
    148     int second_pred
    149 )
    150 {
    151     uint32_t    cmd;
    152     uint32_t    blk_size;
    153     uint32_t    pred_offset;
    154 
    155     /* Determine residual data's block size (16x8 or 16x16)     */
    156     if (FRAME_PICTURE == ctx->picture_structure) {
    157         if ((1 == MBPARAM_MotionType(mb_param)) ||  /* Field MC */
    158             (3 == MBPARAM_MotionType(mb_param))) { /* Dual Prime        */
    159             blk_size = 1;       /* 16 x 8 */
    160         } else {
    161             blk_size = 0;       /* 16 x 16 */
    162         }
    163     } else {
    164         if (2 == MBPARAM_MotionType(mb_param)) { /* Non-Frame MC        */
    165             blk_size = 1;       /* 16 x 8 */
    166         } else {
    167             blk_size = 0; /* 16 x 16 */
    168         }
    169     }
    170 
    171     /* Determine whether this is for 1st MV or 2nd MV */
    172     if (TRUE == second_pred) {
    173         pred_offset = 8;
    174     } else {
    175         pred_offset = 0;
    176     }
    177 
    178     cmd = 0;
    179 
    180     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, INTER_PRED_BLOCK_SIZE,   blk_size);
    181 
    182     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_A, ctx->ref_indexA);
    183     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_B, ctx->ref_indexB);
    184 
    185     if (3 == MBPARAM_MotionType(mb_param)) {  /* Dual Prime */
    186         REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_A_VALID, 1);
    187         REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_B_VALID, 1);
    188     } else {
    189         REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_A_VALID,
    190                           MBPARAM_MotionForward(mb_param));
    191         REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_B_VALID,
    192                           MBPARAM_MotionBackward(mb_param));
    193     }
    194 
    195     if (FRAME_PICTURE == ctx->picture_structure) {
    196         /* Frame picture processing */
    197         if ((1 == MBPARAM_MotionType(mb_param)) ||  /* Field MC */
    198             (3 == MBPARAM_MotionType(mb_param))) { /* Dual Prime        */
    199             if ((1 == MBPARAM_MotionForward(mb_param)) ||
    200                 (3 == MBPARAM_MotionType(mb_param))) {  /* Dual Prime */
    201                 if (second_pred) {
    202                     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION,
    203                                       REF_INDEX_FIELD_A, MBPARAM_MvertFieldSel_2(mb_param));
    204                 } else {
    205                     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION,
    206                                       REF_INDEX_FIELD_A, MBPARAM_MvertFieldSel_0(mb_param));
    207                 }
    208             }
    209 
    210             if ((1 == MBPARAM_MotionBackward(mb_param)) ||
    211                 (3 == MBPARAM_MotionType(mb_param))) {  /* Dual Prime   */
    212                 if (second_pred) {
    213                     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION,
    214                                       REF_INDEX_FIELD_B, MBPARAM_MvertFieldSel_3(mb_param));
    215                 } else {
    216                     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION,
    217                                       REF_INDEX_FIELD_B, MBPARAM_MvertFieldSel_1(mb_param));
    218                 }
    219             }
    220         }
    221     } else {
    222         /* Field picture processing */
    223         if ((0 == MBPARAM_MotionForward(mb_param)) &&
    224             (0 == MBPARAM_MotionBackward(mb_param))) {
    225             REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_A, ctx->ref_indexA);
    226             REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_B, ctx->ref_indexB);
    227         }
    228 
    229         if (1 == MBPARAM_MotionForward(mb_param)) {
    230             if (second_pred) {
    231                 if ((0 == MBPARAM_MvertFieldSel_2(mb_param)) &&
    232                     (PICTURE_CODING_P == ctx->picture_coding_type)) { /* Top field of this frame        */
    233                     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_A, ctx->ref_indexB);
    234                 } else { /* Bottom field of previous frame*/
    235                     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_A, ctx->ref_indexA);
    236                 }
    237 
    238                 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_FIELD_A,
    239                                   MBPARAM_MvertFieldSel_2(mb_param));
    240             } else {
    241                 if (((ctx->picture_structure == BOTTOM_FIELD) != MBPARAM_MvertFieldSel_0(mb_param)) &&
    242                     (PICTURE_CODING_P == ctx->picture_coding_type)) {   /* Top field of this frame      */
    243                     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_A, ctx->ref_indexB);
    244                 } else { /* Bottom field of previous frame*/
    245                     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_A, ctx->ref_indexA);
    246                 }
    247 
    248                 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_FIELD_A,
    249                                   MBPARAM_MvertFieldSel_0(mb_param));
    250             }
    251         }
    252 
    253 
    254         if (1 == MBPARAM_MotionBackward(mb_param)) {
    255             if (second_pred) {
    256                 if ((1 == MBPARAM_MvertFieldSel_3(mb_param)) &&
    257                     (PICTURE_CODING_P == ctx->picture_coding_type)) { /* Top field of this frame        */
    258                     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_B, ctx->ref_indexA);
    259                 } else {        /* Bottom field of previous frame*/
    260                     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_B, ctx->ref_indexB);
    261                 }
    262 
    263                 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_FIELD_B,
    264                                   MBPARAM_MvertFieldSel_3(mb_param));
    265             } else {
    266                 if ((1 == MBPARAM_MvertFieldSel_1(mb_param)) &&
    267                     (PICTURE_CODING_P == ctx->picture_coding_type)) { /* Top field of this frame        */
    268                     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_B, ctx->ref_indexA);
    269                 } else { /* Bottom field of previous frame*/
    270                     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_B, ctx->ref_indexB);
    271                 }
    272 
    273                 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_FIELD_B,
    274                                   MBPARAM_MvertFieldSel_1(mb_param));
    275             }
    276         }
    277     }
    278 
    279     /* Dual Prime */
    280     if (3 == MBPARAM_MotionType(mb_param) && (ctx->picture_structure != FRAME_PICTURE)) {
    281         if (ctx->picture_structure == TOP_FIELD) {
    282             REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_A, 0);
    283             REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_FIELD_A, 0);
    284             REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_FIELD_B, 1);
    285         } else {
    286             REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_A, 1);
    287             REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_FIELD_A, 1);
    288             REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_FIELD_B, 0);
    289         }
    290     }
    291 
    292     psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, INTER_BLOCK_PREDICTION) + pred_offset, cmd);
    293 }
    294 
    295 typedef struct _PSB_MVvalue {
    296     short  horz;
    297     short  vert;
    298 } psb_MVvalue, *psb_MVvalue_p;
    299 
    300 #define MV_LIBVA2PSB(mb_param)                  \
    301 do {                                            \
    302     MVector[0].horz  = mb_param->PMV[0][0][0];  \
    303     MVector[0].vert  = mb_param->PMV[0][0][1];  \
    304                                                 \
    305     MVector[1].horz  = mb_param->PMV[0][1][0];  \
    306     MVector[1].vert  = mb_param->PMV[0][1][1];  \
    307                                                 \
    308     MVector[2].horz  = mb_param->PMV[1][0][0];  \
    309     MVector[2].vert  = mb_param->PMV[1][0][1];  \
    310                                                 \
    311     MVector[3].horz  = mb_param->PMV[1][1][0];  \
    312     MVector[3].vert  = mb_param->PMV[1][1][1];  \
    313 } while (0)
    314 
    315 static void     psb__MPEG2MC_send_motion_vectores(
    316     context_MPEG2MC_p   const   ctx,
    317     psb_cmdbuf_p cmdbuf,
    318     VAMacroblockParameterBufferMPEG2 * const mb_param
    319 )
    320 {
    321     uint32_t            cmd = 0;
    322     uint32_t            MV1Address = 0;
    323     uint32_t            MV2Address = 0;
    324 
    325     psb_MVvalue  MVector[4];
    326 
    327     MV_LIBVA2PSB(mb_param);
    328 
    329     MV1Address = 0x00;
    330     MV2Address = 0x00;
    331 
    332     if (FRAME_PICTURE == ctx->picture_structure) {
    333         /* FRAME PICTURE PROCESSING */
    334         if (2 == MBPARAM_MotionType(mb_param)) {  /* Frame MC */
    335             if ((0 == MBPARAM_MotionForward(mb_param)) &&
    336                 (0 == MBPARAM_MotionBackward(mb_param))) {
    337                 cmd = 0;
    338                 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_X, 0);
    339                 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_Y, 0);
    340                 psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, MOTION_VECTOR) , cmd);
    341             } else {
    342                 if (1 == MBPARAM_MotionForward(mb_param)) {
    343                     cmd = 0;
    344                     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_X, MVector[0].horz << 1);
    345                     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_Y, MVector[0].vert << 1);
    346                     psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, MOTION_VECTOR) , cmd);
    347                 }
    348 
    349                 if (1 == MBPARAM_MotionBackward(mb_param)) {
    350                     cmd = 0;
    351                     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_X, MVector[1].horz << 1);
    352                     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_Y, MVector[1].vert << 1);
    353                     psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, MOTION_VECTOR) + 0x10 , cmd);
    354                 }
    355             }
    356         } else  {
    357             if ((1 == MBPARAM_MotionType(mb_param)) ||  /* Field MC */
    358                 (3 == MBPARAM_MotionType(mb_param))) {  /* Dual Prime */
    359                 /*
    360                  * Vertical motion vectors for fields located in frame pictures
    361                  * should be divided by 2 (MPEG-2 7.6.3.1). Thus the original value
    362                  * contained in the stream is equivalent to 1/4-pel     format; the
    363                  * resolution required by MSVDX.
    364                  */
    365                 if ((1 == MBPARAM_MotionForward(mb_param)) ||
    366                     (3 == MBPARAM_MotionType(mb_param))) {  /* Dual Prime       */
    367                     cmd = 0;
    368                     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_X, MVector[0].horz << 1);
    369                     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_Y, MVector[0].vert);
    370                     psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, MOTION_VECTOR) , cmd);
    371                 }
    372 
    373                 if ((1 == MBPARAM_MotionBackward(mb_param)) ||
    374                     (3 == MBPARAM_MotionType(mb_param))) {  /* Dual Prime */
    375                     cmd = 0;
    376 
    377                     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_X, MVector[1].horz << 1);
    378 
    379                     if (3 == MBPARAM_MotionType(mb_param)) {  /* Dual Prime */
    380                         REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_Y, MVector[1].vert << 1);
    381                     } else {
    382                         REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_Y, MVector[1].vert);
    383                     }
    384                     psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, MOTION_VECTOR) + 0x10 , cmd);
    385                 }
    386 
    387                 /* Fields and Dual Prime are 16x8 and need 2nd inter_block_pred cmd     */
    388                 psb__MPEG2MC_send_interPB_prediction(ctx, cmdbuf, mb_param, IMG_TRUE);
    389 
    390                 if ((1 == MBPARAM_MotionForward(mb_param)) ||
    391                     (3 == MBPARAM_MotionType(mb_param))) {  /* Dual Prime */
    392                     cmd = 0;
    393                     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_X, MVector[2].horz << 1);
    394                     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_Y, MVector[2].vert);
    395                     psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, MOTION_VECTOR) + 0x40 , cmd);
    396                 }
    397 
    398                 if ((1 == MBPARAM_MotionBackward(mb_param)) ||
    399                     (3 == MBPARAM_MotionType(mb_param))) {      /* Dual Prime                   */
    400                     cmd = 0;
    401                     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_X, MVector[3].horz << 1);
    402                     if (3 == MBPARAM_MotionType(mb_param)) {    /* Dual Prime                   */
    403                         REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_Y, MVector[3].vert << 1);
    404                     } else {
    405                         REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_Y, MVector[3].vert);
    406                     }
    407                     psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, MOTION_VECTOR) + 0x50 , cmd);
    408                 }
    409             }
    410         }
    411     } else {
    412         /* FIELD PICTURE PROCESSING */
    413         int MV0index = 0, MV1index = 1;
    414 
    415         if ((ctx->picture_structure == BOTTOM_FIELD) && (3 == MBPARAM_MotionType(mb_param))) {
    416             MV0index = 1;
    417             MV1index = 0;
    418         }
    419 
    420         if ((1 == MBPARAM_MotionForward(mb_param)) ||   /* Forward MV   */
    421             (3 == MBPARAM_MotionType(mb_param))) { /* Dual Prime        */
    422             cmd = 0;
    423             REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_X, MVector[MV0index].horz << 1);
    424             REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_Y, MVector[MV0index].vert << 1);
    425             psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, MOTION_VECTOR) , cmd);
    426 
    427         }
    428 
    429         if ((1 == MBPARAM_MotionBackward(mb_param)) ||  /* Backward MV  */
    430             (3 == MBPARAM_MotionType(mb_param))) { /* Dual Prime        */
    431             cmd = 0;
    432             REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_X, MVector[MV1index].horz << 1);
    433             REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_Y, MVector[MV1index].vert << 1);
    434             psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, MOTION_VECTOR)  + 0x10, cmd);
    435         }
    436 
    437         if (2 == MBPARAM_MotionType(mb_param)) { /* 16x8 MC */
    438             psb__MPEG2MC_send_interPB_prediction(ctx, cmdbuf, mb_param, IMG_TRUE);
    439 
    440             if ((1 == MBPARAM_MotionForward(mb_param)) ||  /* Forward MV */
    441                 (3 == MBPARAM_MotionType(mb_param))) {  /* Dual Prime */
    442                 cmd = 0;
    443                 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_X, MVector[2].horz << 1);
    444                 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_Y, MVector[2].vert << 1);
    445                 psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, MOTION_VECTOR)  + 0x40, cmd);
    446             }
    447 
    448             if ((1 == MBPARAM_MotionBackward(mb_param)) ||      /* Backward MV                          */
    449                 (3 == MBPARAM_MotionType(mb_param))) {  /* Dual Prime                           */
    450                 cmd = 0;
    451                 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_X, MVector[3].horz << 1);
    452                 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_Y, MVector[3].vert << 1);
    453 
    454                 psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, MOTION_VECTOR)  + 0x50, cmd);
    455             }
    456         }
    457     }
    458 }
    459 
    460 
    461 /* Send macroblock_number command to MSVDX. */
    462 static void     psb__MPEG2MC_send_mb_number(
    463     context_MPEG2MC_p   const   ctx,
    464     psb_cmdbuf_p cmdbuf,
    465     const uint32_t mb_addr,
    466     const uint32_t motion_type,
    467     const eMB_CODE_TYPE MB_coding_type
    468 )
    469 {
    470     uint32_t cmd;
    471     uint32_t mb_x;
    472 
    473     /* 3.3.21.  Macroblock Number */
    474     cmd = 0;
    475 
    476     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_NUMBER, MB_ERROR_FLAG, 0);
    477 
    478     /*
    479       MB_FIELD_CODE (MC + VDEB): Indicate if the macroblock is field predicted (when = 1),
    480                                  or frame predicted (when VDEB = 0).
    481           MPEG2: For Interlaced frame, derived from frame_motion_type, else same
    482                  frame/filed type as SLICE_FIELD_TYPE
    483 
    484      */
    485     if (FRAME_PICTURE == ctx->picture_structure) {
    486         if ((0 == motion_type)  ||
    487             (2 == motion_type)) {
    488             /* MB is frame predicted    */
    489             REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_NUMBER, MB_FIELD_CODE, 0);
    490         } else { /* MB is field predicted       */
    491             REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_NUMBER, MB_FIELD_CODE, 1);
    492         }
    493     } else { /* MB is field predicted   */
    494         REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_NUMBER, MB_FIELD_CODE, 1);
    495     }
    496 
    497     ASSERT((0 != ctx->picture_coding_type) && (4 != ctx->picture_coding_type));
    498 
    499     /*
    500       MB_CODE_TYPE (MC + VDEB): Indicate macroblock type is I, P, B or MPEG4 S(GMC).
    501                   0x0: I or SI macroblock
    502                   0x1: P or SP macroblock
    503                   0x2: B macroblock
    504                   0x3: MPEG4 GMC
    505            MPEG2: Derived from macroblock_type
    506      */
    507     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_NUMBER, MB_CODE_TYPE, (uint32_t) MB_coding_type);
    508 
    509 
    510     /*
    511       MB_NO_Y (MC + VDEB): Vertical offset of current Macroblock (where 0 = topmost macroblock of picture)
    512                            Derived from macroblock number divided by picture width in macroblocks.
    513       MB_NO_X (MC + VDEB): Horizontal offset of current Macroblock (where 0 = leftmost macroblock of picture)
    514                            Derived from macroblock number mod picture width in macroblocks.
    515      */
    516     if ((FRAME_PICTURE != ctx->picture_structure) &&
    517         (mb_addr / ctx->picture_width_mb)) {
    518         REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_NUMBER, MB_NO_Y, (mb_addr / ctx->picture_width_mb) * 2);
    519     } else {
    520         REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_NUMBER, MB_NO_Y, mb_addr / ctx->picture_width_mb);
    521     }
    522 
    523     mb_x = mb_addr % ctx->picture_width_mb;
    524     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_NUMBER, MB_NO_X, mb_x);
    525     /*
    526       Only defined for current MB, set to 0 for above1 and above2.
    527               Indicate if MB is on Left Hand Side of slice or picture
    528               0: MB is not on left hand side of slice or picture
    529               1: MB is on left hand side of slice or picture
    530     */
    531     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_NUMBER , MB_SLICE_LHS, ctx->fstmb_slice || (mb_x == 0));
    532     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_NUMBER , MB_SLICE_TOP, 1);
    533 
    534     psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_CMDS, MACROBLOCK_NUMBER) , cmd);
    535 }
    536 
    537 static void psb__MPEG2MC_finalise_residDMA(
    538     context_MPEG2MC_p   const   ctx
    539 )
    540 {
    541     uint32_t *save_idx = ctx->obj_context->cmdbuf->cmd_idx;
    542     ctx->obj_context->cmdbuf->cmd_idx = ctx->lldma_idx;
    543     if (ctx->residual_pendingDMA) {
    544 #if 0
    545         if (ctx->residual_pendingDMA != (ctx->blk_size * ctx->blk_in_buffer)) {
    546             drv_debug_msg(VIDEO_DEBUG_ERROR, "psb__MPEG2MC_finalise_residDMA:residual_pendingDMA=%d(block:%d),"
    547                                "actual data size=%d (block:%d)\n",
    548                                ctx->residual_pendingDMA, ctx->residual_pendingDMA / ctx->blk_size,
    549                                ctx->blk_size * ctx->blk_in_buffer,
    550                                ctx->blk_in_buffer);
    551         }
    552 #endif
    553 
    554         psb_cmdbuf_lldma_write_cmdbuf(ctx->obj_context->cmdbuf,
    555                                       ctx->residual_buf,
    556                                       ctx->residual_sent,
    557                                       ctx->residual_pendingDMA,
    558                                       0,
    559                                       LLDMA_TYPE_RESIDUAL);
    560     } else {
    561         //*ctx->obj_context->cmdbuf->cmd_idx = CMD_NOP;
    562         *ctx->obj_context->cmdbuf->cmd_idx = 0xf000000;
    563     }
    564     ctx->obj_context->cmdbuf->cmd_idx = save_idx;
    565     ctx->residual_sent += ctx->residual_pendingDMA;
    566     ctx->residual_pendingDMA = 0;
    567 }
    568 
    569 static void psb__MPEG2MC_check_segment_residDMA(
    570     context_MPEG2MC_p   const   ctx,
    571     uint32_t min_space
    572 )
    573 {
    574     if (psb_cmdbuf_segment_space(ctx->obj_context->cmdbuf) < min_space) {
    575         psb__MPEG2MC_finalise_residDMA(ctx);
    576 
    577         psb_cmdbuf_next_segment(ctx->obj_context->cmdbuf);
    578 
    579         ctx->lldma_idx = ctx->obj_context->cmdbuf->cmd_idx++; /* Insert the LLDMA record here later */
    580     }
    581 }
    582 
    583 
    584 /* Send residual difference data to MSVDX. */
    585 static void     psb__MPEG2MC_send_residual(
    586     context_MPEG2MC_p   ctx,
    587     uint32_t    pattern_code)
    588 {
    589     uint8_t pattern_code_byte = (uint8_t)(pattern_code >> 6);
    590     uint8_t blocks = 0;
    591 
    592     while (pattern_code_byte) {
    593         blocks += (pattern_code_byte & 1);
    594         pattern_code_byte >>= 1;
    595     }
    596 
    597     if (PICTURE_CODING_I == ctx->picture_coding_type) {
    598         ctx->residual_pendingDMA += blocks * (8 * 8); /* 8bit */
    599     } else {
    600         /* We do not suport ConfigSpatialResid8==1  */
    601         /* ASSERT(ConfigSpatialResid8 == 0); */
    602         ctx->residual_pendingDMA += blocks * (8 * 8) * 2;/*  16 bit */
    603     }
    604 }
    605 
    606 
    607 static void     psb__MPEG2MC_send_slice_parameters(
    608     context_MPEG2MC_p   const   ctx
    609 )
    610 {
    611     psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf;
    612     uint32_t cmd;
    613 
    614     ctx->lldma_idx = ctx->obj_context->cmdbuf->cmd_idx++; /* Insert the LLDMA record here later */
    615 
    616     psb_cmdbuf_reg_start_block(cmdbuf, 0);
    617 
    618     /* 3.3.19.  Slice Params*/
    619     /*
    620       3:2 SLICE_FIELD_TYPE (MC+VDEB)  Indicate if slice is a frame, top fie
    621                       0x0: Top field picture
    622                       0x1: Bottom field picture
    623                       0x2: Frame picture
    624       1:0 SLICE_CODE_TYPE  (MC+VDEB)  Indicate if it is an I, P, B  slice
    625                       0x0: I slice
    626                       0x1: P slice
    627                       0x2: B slice
    628                       0x3: S(GMC) (MPEG4 only)
    629      */
    630     cmd = 0;
    631     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, SLICE_PARAMS, SLICE_FIELD_TYPE,
    632                       ft_libva2msvdx[ctx->picture_structure]);
    633     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, SLICE_PARAMS, SLICE_CODE_TYPE,
    634                       pict_libva2msvdx[ctx->picture_coding_type]);
    635     psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, SLICE_PARAMS), cmd);
    636 
    637     psb_cmdbuf_reg_end_block(cmdbuf);
    638 }
    639 
    640 static void psb__MPEG2MC_send_slice_picture_endcommand(
    641     context_MPEG2MC_p   const   ctx,
    642     int end_picture
    643 )
    644 {
    645     psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf;
    646     uint32_t cmd;
    647 
    648     /*
    649       3.3.22.         End Slice/Picture
    650       Offset:           0x0404
    651       This command is sent at the end of a slice or picture. The final macroblock of slice/picture will not be
    652       processed until this command is sent. The End Slice/Picture commands can be sent more than once
    653       at the end of a slice (provided no other commands are interleaved).
    654       If the command is sent more than once at the end of a slice, the first command should indicate the
    655       end of the slice (no data bits set) with repeat commands used to indicate end of slice, flushing VDEB
    656       buffers or picture end. The FLUSH_VDEB_BUFFERS bit should not be set in any repeat commands
    657       sent after a command in which the PICTURE_END bit is set.
    658       31:2 -                       Reserved
    659       1    FLUSH_VDEB_BUFFERS(VDEB) If set, indicates VDEB should flush its internal buffers to system memory
    660                                     when slice processing is complete
    661       0    PICTURE_END(MC + VDEB)   If set, indicates both Picture and Slice end, otherwise Slice end
    662      */
    663     psb_cmdbuf_reg_start_block(cmdbuf, 0);
    664 
    665     psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, END_SLICE_PICTURE), 0);
    666 
    667     if (end_picture) {
    668         cmd = 0;
    669         REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, END_SLICE_PICTURE, PICTURE_END, end_picture);
    670         psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_CMDS, END_SLICE_PICTURE), cmd);
    671     }
    672 
    673     psb_cmdbuf_reg_end_block(cmdbuf);
    674 }
    675 
    676 static void     psb__MPEG2MC_send_highlevel_commands(
    677     context_MPEG2MC_p   const   ctx
    678 )
    679 {
    680     psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf;
    681     psb_surface_p target_surface = ctx->obj_context->current_render_target->psb_surface;
    682 
    683     psb_cmdbuf_reg_start_block(cmdbuf, 0);
    684 
    685     /* 3.3.1.   Display Picture Size */
    686     psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, DISPLAY_PICTURE_SIZE), ctx->display_picture_size);
    687 
    688     /* 3.3.2.   Coded Picture Size*/
    689     psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, CODED_PICTURE_SIZE), ctx->coded_picture_size);
    690 
    691     /* 3.3.3.   Operating Mode */
    692     psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, OPERATING_MODE), ctx->obj_context->operating_mode);
    693 
    694     /* 3.3.4.   Luma Reconstructed Picture Base Address */
    695     psb_cmdbuf_reg_set_RELOC(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, LUMA_RECONSTRUCTED_PICTURE_BASE_ADDRESSES),
    696                              &target_surface->buf, 0);
    697 
    698     /* 3.3.5.   Chroma Reconstructed Picture Base Address */
    699     psb_cmdbuf_reg_set_RELOC(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, CHROMA_RECONSTRUCTED_PICTURE_BASE_ADDRESSES),
    700                              &target_surface->buf, target_surface->chroma_offset);
    701 
    702     /* 3.3.13.  Reference Picture Base Addresses */
    703     /*
    704       Reference Picture Base Addresses
    705               Offset:          0x0100 + N*8 = Luma base addresses
    706               Offset:          0x0104 + N*8 = Chroma base addresses
    707       This register can store up to 16 luma picture base addresses and 16 chroma picture base addresses.
    708       Luma and chroma ref base registers are interleaved.
    709 
    710       Bit      Symbol                    Used     Description
    711               31:12    LUMA_REF_BASE_ADDR        MC       Luma picture base byte address [31:12]
    712               11:0     -                                  Reserved
    713       Bit      Symbol                     Used     Description
    714               31:12    CHROMA_REF_BASE_ADDR       MC       Chroma picture base byte address [31:12]
    715               11:0     -                                   Reserved
    716       -   In MPEG2, the registers at N=0 are always used to store the base address of the luma and
    717       chroma buffers of the most recently decoded reference picture. The registers at N=1 are used
    718       to store the base address of the luma and chroma buffers of the older reference picture, if
    719       more than one reference picture is used. This means that when decoding a P picture the
    720       forward reference pictures address is at index 0. When decoding a B-picture the backward
    721       reference pictures address is at index 0 and the address of the forward reference picture 
    722       which was decoded earlier than the backward reference  is at index 1.
    723      */
    724 
    725     /* WABA: backward / forward refs are always set, even when they aren't strictly needed */
    726     psb_surface_p forward_surface = ctx->forward_ref_surface->psb_surface;
    727     psb_surface_p backward_surface = ctx->backward_ref_surface->psb_surface;
    728 
    729     if (backward_surface) {
    730         psb_cmdbuf_reg_set_RELOC(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, REFERENCE_PICTURE_BASE_ADDRESSES) + (0 * 8),
    731                                  &backward_surface->buf, 0);
    732 
    733         psb_cmdbuf_reg_set_RELOC(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, REFERENCE_PICTURE_BASE_ADDRESSES) + 4 + (0 * 8),
    734                                  &backward_surface->buf, backward_surface->chroma_offset);
    735     }
    736     if (forward_surface) {
    737         psb_cmdbuf_reg_set_RELOC(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, REFERENCE_PICTURE_BASE_ADDRESSES) + (1 * 8),
    738                                  &forward_surface->buf, 0);
    739 
    740         psb_cmdbuf_reg_set_RELOC(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, REFERENCE_PICTURE_BASE_ADDRESSES) + 4 + (1 * 8),
    741                                  &forward_surface->buf, forward_surface->chroma_offset);
    742     }
    743 
    744     /*
    745      * VDMC_RESIDUAL_DIRECT_INSERT_CONTROL, spec p 159
    746      * 0 VDMC_RESIDUAL_DIRECT_CONTROL (VDMC) residual direct insert control.
    747      *           Control insertion of spatial residual data. When set to 1 residual
    748      *           data taken from writes to VDMC_RESIDUAL_DIRECT_INSERT_DATA
    749      *           when set to 0, residual data taken from vEC
    750      */
    751     psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_VDMC, CR_VDMC_RESIDUAL_DIRECT_INSERT_CONTROL), 1);
    752 
    753     psb_cmdbuf_reg_end_block(cmdbuf);
    754 }
    755 
    756 
    757 
    758 /* Control building of the MSVDX command buffer for a B and P pictures.*/
    759 static void     psb__MPEG2MC_interPB_mb(
    760     context_MPEG2MC_p const     ctx,
    761     VAMacroblockParameterBufferMPEG2 * const    mb_param
    762 )
    763 {
    764     psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf;
    765     uint32_t cmd;
    766 
    767     psb_cmdbuf_reg_start_block(cmdbuf, 0);
    768 
    769     /* 3.3.21.  Macroblock Number */
    770     psb__MPEG2MC_send_mb_number(ctx, cmdbuf, mb_param->macroblock_address, MBPARAM_MotionType(mb_param),
    771                                 MBPARAM_IntraMacroblock(mb_param) ? MB_CODE_TYPE_I : pict_libva2msvdx[ctx->picture_coding_type]
    772                                );
    773 
    774     cmd = 0;
    775     /* Only used for direct insert of residual data;-
    776        00 = 8-bit signed data
    777        01 = 8-bit unsigned data
    778        10 = 16-bit signed
    779        11 = Reserved
    780     */
    781     /* TODO:: ASSERT(ConfigSpatialResid8==0 ); */
    782     if (MBPARAM_IntraMacroblock(mb_param)) {
    783         if (1/* TODO:: ConfigIntraResidUnsigned == 0 */) {
    784             /* sent as as 16 bit signed relative to 128*/
    785             REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, VA_ADD_128, 1);
    786             REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, VA_DATA_FORMAT, 2);
    787         } else { /* ConfigIntraResidUnsigned == 1 */
    788             /* 16 bit unsigned unsigned relative to 0*/
    789             REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, VA_ADD_128, 0);
    790             REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, VA_DATA_FORMAT,       2);
    791         }
    792     } else {
    793         /* For non-intra in Inter frames : 16 bit signed */
    794         REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, VA_ADD_128, 0);
    795         REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, VA_DATA_FORMAT, 2);
    796     }
    797 
    798 
    799     if (FRAME_PICTURE == ctx->picture_structure) {
    800         /* mb_param->macroblock_modes.bits.dct_type =1: field DCT */
    801         REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, RESIDUAL_FIELD_CODED, mb_param->macroblock_modes.bits.dct_type ? 1 : 0);
    802     } else {
    803         REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, RESIDUAL_FIELD_CODED, 1);
    804     }
    805 
    806     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, CR_FROM_VEC,
    807                       ((MBPARAM_CodedBlockPattern(mb_param) & 0x40) ? 1 : 0));
    808     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, CB_FROM_VEC,
    809                       ((MBPARAM_CodedBlockPattern(mb_param) & 0x80) ? 1 : 0));
    810     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, Y3_FROM_VEC,
    811                       ((MBPARAM_CodedBlockPattern(mb_param) & 0x100) ? 1 : 0));
    812     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, Y2_FROM_VEC,
    813                       ((MBPARAM_CodedBlockPattern(mb_param) & 0x200) ? 1 : 0));
    814     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, Y1_FROM_VEC,
    815                       ((MBPARAM_CodedBlockPattern(mb_param) & 0x400) ? 1 : 0));
    816     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, Y0_FROM_VEC,
    817                       ((MBPARAM_CodedBlockPattern(mb_param) & 0x800) ? 1 : 0));
    818     psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT) , cmd);
    819 
    820     /* Send Residuals   */
    821     if (MBPARAM_IntraMacroblock(mb_param)) {
    822         cmd = 0;
    823         REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTRA_BLOCK_PREDICTION, INTRA_PRED_MODE0, 0);
    824         REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTRA_BLOCK_PREDICTION, INTRA_PRED_MODE1, 0);
    825         REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTRA_BLOCK_PREDICTION, INTRA_PRED_MODE2, 0);
    826         REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTRA_BLOCK_PREDICTION, INTRA_PRED_MODE3, 0);
    827         psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_CMDS, INTRA_BLOCK_PREDICTION) , cmd);
    828 
    829         psb__MPEG2MC_send_residual(ctx, MBPARAM_CodedBlockPattern(mb_param));
    830     } else {
    831         psb__MPEG2MC_send_interPB_prediction(ctx, cmdbuf, mb_param, IMG_FALSE);
    832 
    833         /* Send motion vectors  */
    834         psb__MPEG2MC_send_motion_vectores(ctx, cmdbuf, mb_param);
    835 
    836         psb__MPEG2MC_send_residual(ctx, MBPARAM_CodedBlockPattern(mb_param));
    837     }
    838 
    839     psb_cmdbuf_reg_end_block(cmdbuf);
    840 }
    841 
    842 
    843 
    844 /* Process Macroblocks of a B or P picture.*/
    845 static VAStatus psb__MPEG2MC_process_mbs_interPB(
    846     context_MPEG2MC_p   const   ctx
    847 )
    848 {
    849     uint32_t    skip_count = 0;
    850     VAMacroblockParameterBufferMPEG2 *mb_param  = NULL;
    851     VAMacroblockParameterBufferMPEG2 mbparam_skip;
    852 
    853     uint32_t mb_pending = ctx->mb_in_buffer;
    854     uint32_t mb_addr = ctx->mb_first_addr;
    855     uint32_t mb_last = mb_addr + mb_pending;
    856     mb_param = (VAMacroblockParameterBufferMPEG2 *) ctx->mb_param;
    857 
    858     /* Proccess all VA_MBctrl_P_HostResidDiff_1 structure in the buffer
    859      * - this may genererate more macroblocks due to skipped
    860      */
    861     while (mb_pending || skip_count) {
    862         uint32_t mb_in_buffer = (ctx->picture_width_mb);
    863         psb_cmdbuf_p cmdbuf;
    864         unsigned char *cmd_start;
    865 
    866         ctx->fstmb_slice = IMG_TRUE;
    867 
    868         psb_context_get_next_cmdbuf(ctx->obj_context);
    869         cmdbuf = ctx->obj_context->cmdbuf;
    870         cmd_start = (unsigned char *) cmdbuf->cmd_idx;
    871 
    872         /* Build the high-level commands */
    873         psb__MPEG2MC_send_highlevel_commands(ctx);
    874 
    875         psb__MPEG2MC_send_slice_parameters(ctx);
    876 
    877         /* Process all the macroblocks in the slice */
    878         while ((mb_pending || skip_count) && mb_in_buffer--) {
    879             /* Check for segment space - do we have space for at least one more
    880              * worst case InterMB plus completion
    881             */
    882             psb__MPEG2MC_check_segment_residDMA(ctx, INTER_MB_WORST_CASE + 2);
    883 
    884             if (skip_count) {  /* Skipped macroblock processing */
    885                 mbparam_skip.macroblock_address++;
    886 
    887                 ASSERT(mb_param->macroblock_address < ctx->size_mb);
    888                 ASSERT(mbparam_skip.macroblock_address  == mb_addr);
    889 
    890                 psb__MPEG2MC_interPB_mb(ctx, &mbparam_skip);
    891 
    892                 skip_count--;
    893             } else {
    894                 ASSERT(mb_pending);
    895                 ASSERT(mb_param->macroblock_address < ctx->size_mb);
    896                 ASSERT(mb_param->macroblock_address  == mb_addr);
    897 
    898                 psb__MPEG2MC_interPB_mb(ctx, mb_param);
    899 
    900                 skip_count = MBPARAM_MBskipsFollowing(mb_param);
    901                 if (skip_count) {
    902                     memcpy(&mbparam_skip, mb_param, sizeof(mbparam_skip));
    903                 }
    904 
    905                 mb_param++;
    906                 mb_pending--;
    907             }
    908 
    909             ctx->fstmb_slice = IMG_FALSE;
    910 
    911             mb_addr++;
    912         }
    913 
    914         /* Tell hardware we're done     */
    915         psb__MPEG2MC_send_slice_picture_endcommand(ctx, (mb_pending == 0) && (skip_count == 0) && (ctx->size_mb == mb_last));
    916         psb__MPEG2MC_finalise_residDMA(ctx);
    917 
    918         /* write_kick */
    919         *cmdbuf->cmd_idx++ = CMD_COMPLETION;
    920 
    921         ctx->obj_context->video_op = psb_video_mc;
    922         ctx->obj_context->flags = (mb_pending == 0) && (skip_count == 0) && (ctx->size_mb == mb_last) ? FW_VA_RENDER_IS_LAST_SLICE : 0;
    923         ctx->obj_context->first_mb = 0;
    924         ctx->obj_context->last_mb = 0;
    925         psb_context_submit_cmdbuf(ctx->obj_context);
    926 
    927         /* check if the remained cmdbuf size can fill the commands of next slice */
    928         if (1 || (cmdbuf->lldma_base - (unsigned char *) cmdbuf->cmd_idx) < ((unsigned char *) cmdbuf->cmd_idx - cmd_start))
    929             psb_context_flush_cmdbuf(ctx->obj_context);
    930     }
    931 
    932     return VA_STATUS_SUCCESS;
    933 }
    934 
    935 
    936 static void     psb__MPEG2MC_intra_mb(
    937     context_MPEG2MC_p const ctx,
    938     const VAMacroblockParameterBufferMPEG2* const mb_param
    939 )
    940 {
    941     psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf;
    942     uint32_t cmd;
    943 
    944     psb_cmdbuf_reg_start_block(cmdbuf, 0);
    945 
    946     /* 3.3.21.  Macroblock Number */
    947     psb__MPEG2MC_send_mb_number(ctx, cmdbuf, mb_param->macroblock_address, MBPARAM_MotionType(mb_param), MB_CODE_TYPE_I);
    948 
    949     /*3.3.25.   Macroblock Residual Format */
    950     cmd = 0;
    951 
    952     /* In INTRA pictures, spatial-blocks are always 8bit when BBP is 8 */
    953     /*  00 = 8-bit signed data
    954      *  01 = 8-bit unsigned data
    955      */
    956     if (1/* TODO:: ConfigIntraResidUnsigned==0 */) {
    957         /* spec p67:
    958          * VA_ADD_128 MC Only used for direct insert of residual data;-
    959          *       0: add 0 to residual data input
    960          *       1: indicates 128 should be added to residual data input
    961          *
    962          * VA_DATA_FORMAT:Only used for direct insert of residual data;-
    963          *       0x0: 8-bit signed data
    964          *       0x1: 8-bit unsigned data
    965          *       0x2: 16-bit signed
    966          */
    967         /* Sent as  8 bit signed relative to 128 */
    968         REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, VA_DATA_FORMAT, 0);  /* ok ish */
    969         REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, VA_ADD_128,       1);   /* ok ish */
    970     } else {
    971         /* Sent as 8 bit unsigned relative to 0 */
    972         REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, VA_DATA_FORMAT, 1);
    973         REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, VA_ADD_128,       0);
    974     }
    975 
    976     if (FRAME_PICTURE == ctx->picture_structure) {
    977         /*
    978          * RESIDUAL_FIELD_CODED MC
    979          *               0: residual data frame coded
    980          *               1: (luma)residual data field coded
    981          *       N.B. For VC1, MPEG4 and MPEG2, if SLICE_FIELD_TYPE =
    982          *            frame, chroma residual will be frame coded, even if the luma
    983          *            residual is field coded.
    984          */
    985         /*
    986          * (VA:wMBType bit 5: FieldResidual, wMBtype & 0x20)/libVA(dct_type:1 field DCT):
    987          * Indicates whether the residual difference blocks use a field IDCT structure as specified in MPEG-2.
    988          *
    989          * Must be 1 if the bPicStructure member of VA_PictureParameters is 1 or 2. When used for MPEG-2,
    990          * FieldResidual must be zero if the frame_pred_frame_DCT variable in the MPEG-2 syntax is 1, and
    991          * must be equal to the dct_type variable in the MPEG-2 syntax if dct_type is present for the macroblock.
    992          */
    993         REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT,
    994                           RESIDUAL_FIELD_CODED, ((mb_param->macroblock_modes.bits.dct_type) ? 1 : 0));
    995     } else {
    996         REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, RESIDUAL_FIELD_CODED, 1);
    997     }
    998 
    999     /*   CR_FROM_VEC MC  0: constant zero residual
   1000                         1: block Cr provided by VEC
   1001                         (If REVERSE_FLAG_ORDER=1, this bit indicates if Y0 provided)
   1002          CB_FROM_VEC MC 0: constant zero residual
   1003                         1: block Cb provided by VEC
   1004                      (If REVERSE_FLAG_ORDER=1, this bit indicates if Y1 provided)
   1005          Y3_FROM_VEC MC 0: constant zero residual
   1006                         1: block Y3 provided by VEC
   1007                         (If REVERSE_FLAG_ORDER=1, this bit indicates if Y2 provided)
   1008          Y2_FROM_VEC MC 0: constant zero residual
   1009                         1: block Y2 provided by VEC
   1010                          (If REVERSE_FLAG_ORDER=1, this bit indicates if Y3 provided)
   1011          Y1_FROM_VEC MC 0: constant zero residual
   1012                         1: block Y1 provided by VEC
   1013                          (If REVERSE_FLAG_ORDER=1, this bit indicates if Cb provided)
   1014          Y0_FROM_VEC MC 0: constant zero residual
   1015                         1: block Y0 provided by VEC
   1016                          (If REVERSE_FLAG_ORDER=1, this bit indicates if Cr provided)
   1017     */
   1018     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, CR_FROM_VEC,
   1019                       ((MBPARAM_CodedBlockPattern(mb_param) & 0x40) ? 1 : 0));
   1020     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, CB_FROM_VEC,
   1021                       ((MBPARAM_CodedBlockPattern(mb_param) & 0x80) ? 1 : 0));
   1022     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, Y3_FROM_VEC,
   1023                       ((MBPARAM_CodedBlockPattern(mb_param) & 0x100) ? 1 : 0));
   1024     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, Y2_FROM_VEC,
   1025                       ((MBPARAM_CodedBlockPattern(mb_param) & 0x200) ? 1 : 0));
   1026     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, Y1_FROM_VEC,
   1027                       ((MBPARAM_CodedBlockPattern(mb_param) & 0x400) ? 1 : 0));
   1028     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, Y0_FROM_VEC,
   1029                       ((MBPARAM_CodedBlockPattern(mb_param) & 0x800) ? 1 : 0));
   1030     psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT) , cmd);
   1031 
   1032     /* Send Residuals, spec p69,h264 only */
   1033     cmd = 0;
   1034     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTRA_BLOCK_PREDICTION, INTRA_PRED_MODE0, 0);
   1035     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTRA_BLOCK_PREDICTION, INTRA_PRED_MODE1, 0);
   1036     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTRA_BLOCK_PREDICTION, INTRA_PRED_MODE2, 0);
   1037     REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTRA_BLOCK_PREDICTION, INTRA_PRED_MODE3, 0);
   1038     psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_CMDS, INTRA_BLOCK_PREDICTION) , cmd);
   1039 
   1040     psb__MPEG2MC_send_residual(ctx, MBPARAM_CodedBlockPattern(mb_param));
   1041 
   1042     psb_cmdbuf_reg_end_block(cmdbuf);
   1043 }
   1044 
   1045 
   1046 static VAStatus psb__MPEG2MC_process_mbs_intra(
   1047     context_MPEG2MC_p   const   ctx
   1048 )
   1049 {
   1050     const VAMacroblockParameterBufferMPEG2* mb_param = NULL;
   1051     uint32_t mb_pending = ctx->mb_in_buffer;
   1052     uint32_t mb_addr = ctx->mb_first_addr;
   1053     uint32_t mb_last = mb_addr + mb_pending;
   1054 
   1055     mb_param = (VAMacroblockParameterBufferMPEG2*) ctx->mb_param;
   1056 
   1057     while (mb_pending) { /* one slice per loop */
   1058         uint32_t mb_in_buffer =  min(mb_pending, ctx->picture_width_mb);
   1059         psb_cmdbuf_p cmdbuf;
   1060         unsigned char *cmd_start;
   1061 
   1062         mb_pending -= mb_in_buffer;
   1063 
   1064         psb_context_get_next_cmdbuf(ctx->obj_context);
   1065         cmdbuf = ctx->obj_context->cmdbuf;
   1066         cmd_start = (unsigned char *) cmdbuf->cmd_idx;
   1067 
   1068         ctx->fstmb_slice = IMG_TRUE;
   1069 
   1070         /* Build the high-level commands */
   1071         psb__MPEG2MC_send_highlevel_commands(ctx);
   1072 
   1073         psb__MPEG2MC_send_slice_parameters(ctx);
   1074 
   1075         /* Process all the macroblocks in the slice */
   1076         while (mb_in_buffer--) { /* for every MB */
   1077             ASSERT(mb_param->macroblock_address < ctx->size_mb);
   1078             ASSERT(mb_param->macroblock_address  == mb_addr);
   1079 
   1080             /* Check for segment space - do we have space for at least one more
   1081              * worst case IntraMB plus completion
   1082             */
   1083             psb__MPEG2MC_check_segment_residDMA(ctx, INTRA_MB_WORST_CASE + 2);
   1084 
   1085             psb__MPEG2MC_intra_mb(ctx, mb_param);
   1086 
   1087             mb_param++; /* next macroblock parameter */
   1088             mb_addr++;
   1089 
   1090             ctx->fstmb_slice = IMG_FALSE;
   1091         }
   1092 
   1093         psb__MPEG2MC_send_slice_picture_endcommand(ctx, (mb_pending == 0) && (ctx->size_mb == mb_last)); /* Tell hardware we're done    */
   1094 
   1095         psb__MPEG2MC_finalise_residDMA(ctx);
   1096 
   1097         /* write_kick */
   1098         *cmdbuf->cmd_idx++ = CMD_COMPLETION;
   1099 
   1100         ctx->obj_context->video_op = psb_video_mc;
   1101         ctx->obj_context->flags = (mb_pending == 0) && (ctx->size_mb == mb_last) ? FW_VA_RENDER_IS_LAST_SLICE : 0;
   1102         ctx->obj_context->first_mb = 0;
   1103         ctx->obj_context->last_mb = 0;
   1104         psb_context_submit_cmdbuf(ctx->obj_context);
   1105 
   1106         /* check if the remained cmdbuf size can fill the commands of next slice */
   1107         if (1 || (cmdbuf->lldma_base - (unsigned char *) cmdbuf->cmd_idx) < ((unsigned char *) cmdbuf->cmd_idx - cmd_start))
   1108             psb_context_flush_cmdbuf(ctx->obj_context);
   1109     }
   1110 
   1111     //ASSERT(ctx->residual_bytes == 0); /* There should be no more data left */
   1112 
   1113     return VA_STATUS_SUCCESS;
   1114 }
   1115 
   1116 
   1117 static VAStatus psb__MPEG2MC_process_picture_param(context_MPEG2MC_p ctx, object_buffer_p obj_buffer)
   1118 {
   1119     int coded_pic_height;
   1120 
   1121     /* Take a copy of the picture parameters */
   1122     ctx->pic_params = (VAPictureParameterBufferMPEG2 *) obj_buffer->buffer_data;
   1123     obj_buffer->buffer_data = NULL;
   1124     obj_buffer->size = 0;
   1125 
   1126     ctx->picture_coding_type = ctx->pic_params->picture_coding_type;
   1127     ctx->picture_structure = ctx->pic_params->picture_coding_extension.bits.picture_structure;
   1128 
   1129     ctx->forward_ref_surface = SURFACE(ctx->pic_params->forward_reference_picture);
   1130     ctx->backward_ref_surface = SURFACE(ctx->pic_params->backward_reference_picture);
   1131 
   1132     /* Set picture type and reference indices for reference frames */
   1133     if (ctx->picture_coding_type != PICTURE_CODING_I) {
   1134         if (ctx->pic_params->picture_coding_extension.bits.is_first_field) { /* first field */
   1135             if (ctx->backward_ref_surface) {
   1136                 ctx->picture_coding_type = PICTURE_CODING_B;
   1137                 ctx->ref_indexA = 0x01;/* Forward reference frame*/
   1138                 ctx->ref_indexB = 0x00;/* Backward reference frame*/
   1139             } else {
   1140                 ctx->picture_coding_type =  PICTURE_CODING_P;
   1141                 ctx->ref_indexA = 0x00; /* Always reference frame 0*/
   1142             }
   1143         } else {
   1144             if ((PICTURE_CODING_B == ctx->picture_coding_type) && (ctx->backward_ref_surface)) {
   1145                 ctx->picture_coding_type = PICTURE_CODING_B;
   1146                 ctx->ref_indexA = 0x01; /* Forward reference frame*/
   1147                 ctx->ref_indexB = 0x00;/* Backward reference frame */
   1148             } else {
   1149                 ctx->picture_coding_type = PICTURE_CODING_P;
   1150                 if (ctx->forward_ref_surface) {
   1151                     ctx->ref_indexA = 0x00;
   1152                 } else {
   1153                     ctx->ref_indexA = 0x01;
   1154                     ctx->ref_indexB = 0x00;
   1155                 }
   1156             }
   1157         }
   1158     }
   1159     ctx->pic_params->picture_coding_type = ctx->picture_coding_type;
   1160 
   1161     /* residual data size per element */
   1162     if (ctx->picture_coding_type == PICTURE_CODING_I) {
   1163         ctx->blk_size = 64; /* unsigned char */
   1164     } else {
   1165         ctx->blk_size = 2 * 64; /* unsigned short */
   1166     }
   1167 
   1168     if (ctx->picture_coding_type != PICTURE_CODING_I) {
   1169         if (ctx->backward_ref_surface) {
   1170             if (ctx->forward_ref_surface == NULL)
   1171                 ctx->forward_ref_surface = ctx->backward_ref_surface;
   1172         } else {
   1173             ctx->backward_ref_surface = ctx->forward_ref_surface;
   1174         }
   1175     }
   1176     if (NULL == ctx->backward_ref_surface) {
   1177         ctx->backward_ref_surface = ctx->obj_context->current_render_target;
   1178     }
   1179     if (NULL == ctx->forward_ref_surface) {
   1180         ctx->forward_ref_surface = ctx->obj_context->current_render_target;
   1181     }
   1182 
   1183     ctx->coded_picture_width = ctx->pic_params->horizontal_size;
   1184     ctx->coded_picture_height = ctx->pic_params->vertical_size;
   1185     ctx->picture_width_mb = ctx->pic_params->horizontal_size / 16;
   1186     if (ctx->pic_params->picture_coding_extension.bits.progressive_frame == 1) /* should be progressive_sequence? */
   1187         ctx->picture_height_mb = (ctx->coded_picture_height + 15) / 16;
   1188     else {
   1189         if (FRAME_PICTURE != ctx->picture_structure) { /*Interlaced Field Pictures */
   1190             ctx->picture_height_mb = ((ctx->coded_picture_height + 31) / 32);
   1191         } else {
   1192             ctx->picture_height_mb = 2 * ((ctx->coded_picture_height + 31) / 32);
   1193         }
   1194     }
   1195     coded_pic_height = (ctx->picture_structure != FRAME_PICTURE) ?
   1196                        ((ctx->picture_height_mb) * 32) : ((ctx->picture_height_mb) * 16);
   1197     ctx->size_mb = ctx->picture_width_mb * (coded_pic_height >> 4);
   1198 
   1199     ctx->display_picture_size = 0;
   1200     REGIO_WRITE_FIELD_LITE(ctx->display_picture_size, MSVDX_CMDS,
   1201                            DISPLAY_PICTURE_SIZE, DISPLAY_PICTURE_HEIGHT, ctx->coded_picture_height - 1);
   1202     REGIO_WRITE_FIELD_LITE(ctx->display_picture_size, MSVDX_CMDS,
   1203                            DISPLAY_PICTURE_SIZE, DISPLAY_PICTURE_WIDTH, ctx->coded_picture_width - 1);
   1204 
   1205     ctx->coded_picture_size = 0;
   1206     REGIO_WRITE_FIELD_LITE(ctx->coded_picture_size, MSVDX_CMDS,
   1207                            CODED_PICTURE_SIZE, CODED_PICTURE_HEIGHT, ctx->coded_picture_height - 1);
   1208     REGIO_WRITE_FIELD_LITE(ctx->coded_picture_size, MSVDX_CMDS,
   1209                            CODED_PICTURE_SIZE, CODED_PICTURE_WIDTH, ctx->coded_picture_width - 1);
   1210 
   1211     ctx->obj_context->operating_mode = 0;
   1212     REGIO_WRITE_FIELD(ctx->obj_context->operating_mode, MSVDX_CMDS, OPERATING_MODE, CHROMA_FORMAT,  1);
   1213     REGIO_WRITE_FIELD(ctx->obj_context->operating_mode, MSVDX_CMDS, OPERATING_MODE, ASYNC_MODE,     1);
   1214     /* 0 = VDMC and VDEB active.  1 = VDEB pass-thru. */
   1215     REGIO_WRITE_FIELD(ctx->obj_context->operating_mode, MSVDX_CMDS, OPERATING_MODE,
   1216                       CODEC_MODE, CODEC_MODE_MPEG2);
   1217     REGIO_WRITE_FIELD(ctx->obj_context->operating_mode, MSVDX_CMDS, OPERATING_MODE,
   1218                       CODEC_PROFILE,  CODEC_PROFILE_MPEG2_MAIN);
   1219     REGIO_WRITE_FIELD(ctx->obj_context->operating_mode, MSVDX_CMDS, OPERATING_MODE,
   1220                       ROW_STRIDE, (ctx->obj_context->current_render_target->psb_surface->stride_mode));
   1221 
   1222     return VA_STATUS_SUCCESS;
   1223 }
   1224 
   1225 
   1226 
   1227 static void psb_MPEG2MC_QueryConfigAttributes(
   1228     VAProfile profile,
   1229     VAEntrypoint entrypoint,
   1230     VAConfigAttrib *attrib_list,
   1231     int num_attribs)
   1232 {
   1233     /* No MPEG2 specific attributes */
   1234 }
   1235 
   1236 static VAStatus psb_MPEG2MC_ValidateConfig(
   1237     object_config_p obj_config)
   1238 {
   1239     int i;
   1240     /* Check all attributes */
   1241     for (i = 0; i < obj_config->attrib_count; i++) {
   1242         switch (obj_config->attrib_list[i].type) {
   1243         case VAConfigAttribRTFormat:
   1244             /* Ignore */
   1245             break;
   1246 
   1247         default:
   1248             return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED;
   1249         }
   1250     }
   1251 
   1252     return VA_STATUS_SUCCESS;
   1253 }
   1254 
   1255 static VAStatus psb__MPEG2MC_check_legal_picture(object_context_p obj_context, object_config_p obj_config)
   1256 {
   1257     VAStatus vaStatus = VA_STATUS_SUCCESS;
   1258 
   1259     if (NULL == obj_context) {
   1260         vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT;
   1261         DEBUG_FAILURE;
   1262         return vaStatus;
   1263     }
   1264 
   1265     if (NULL == obj_config) {
   1266         vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
   1267         DEBUG_FAILURE;
   1268         return vaStatus;
   1269     }
   1270 
   1271     /* MSVDX decode capability for MPEG2:
   1272      *     MP@HL
   1273      *
   1274      * Refer to Table 8-11 (Upper bounds for luminance sample rate) of ISO/IEC 13818-2: 1995(E),
   1275      * and the "MSVDX MPEG2 decode capability" table of "Poulsbo Media Software Overview"
   1276      */
   1277 
   1278     switch (obj_config->profile) {
   1279     case VAProfileMPEG2Simple:
   1280         if ((obj_context->picture_width <= 0) || (obj_context->picture_width > 352)
   1281             || (obj_context->picture_height <= 0) || (obj_context->picture_height > 288)) {
   1282             vaStatus = VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED;
   1283         }
   1284         break;
   1285 
   1286     case VAProfileMPEG2Main:
   1287         if ((obj_context->picture_width <= 0) || (obj_context->picture_width > 1920)
   1288             || (obj_context->picture_height <= 0) || (obj_context->picture_height > 1088)) {
   1289             vaStatus = VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED;
   1290         }
   1291         break;
   1292 
   1293     default:
   1294         vaStatus = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
   1295         break;
   1296     }
   1297 
   1298     return vaStatus;
   1299 }
   1300 
   1301 static VAStatus psb_MPEG2MC_CreateContext(
   1302     object_context_p obj_context,
   1303     object_config_p obj_config)
   1304 {
   1305     VAStatus vaStatus = VA_STATUS_SUCCESS;
   1306     context_MPEG2MC_p ctx;
   1307 
   1308     /* Validate flag */
   1309     /* Validate picture dimensions */
   1310     vaStatus = psb__MPEG2MC_check_legal_picture(obj_context, obj_config);
   1311     if (VA_STATUS_SUCCESS != vaStatus) {
   1312         DEBUG_FAILURE;
   1313         return vaStatus;
   1314     }
   1315 
   1316     if (obj_context->num_render_targets < 1) {
   1317         vaStatus = VA_STATUS_ERROR_UNKNOWN;
   1318         DEBUG_FAILURE;
   1319         return vaStatus;
   1320     }
   1321 
   1322     ctx = (context_MPEG2MC_p) calloc(1, sizeof(struct context_MPEG2MC_s));
   1323     if (NULL == ctx) {
   1324         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
   1325         DEBUG_FAILURE;
   1326         return vaStatus;
   1327     }
   1328 
   1329     /* TODO: initialize ctx content */
   1330     obj_context->format_data = (void*) ctx;
   1331     ctx->obj_context = obj_context;
   1332     ctx->pic_params = NULL;
   1333     /* TODO create and map buffer */
   1334 
   1335     return vaStatus;
   1336 }
   1337 
   1338 
   1339 static void psb_MPEG2MC_DestroyContext(
   1340     object_context_p obj_context)
   1341 {
   1342     INIT_CONTEXT_MPEG2MC;
   1343 
   1344     /* TODO:unmap and destroy buffers */
   1345     if (ctx->pic_params) {
   1346         free(ctx->pic_params);
   1347         ctx->pic_params = NULL;
   1348     }
   1349 
   1350     free(obj_context->format_data);
   1351     obj_context->format_data = NULL;
   1352 }
   1353 
   1354 static VAStatus psb_MPEG2MC_BeginPicture(
   1355     object_context_p obj_context)
   1356 {
   1357     INIT_CONTEXT_MPEG2MC;
   1358 
   1359 #if 0 /* clear surface for debugging */
   1360     unsigned char *surface_data = NULL;
   1361     static psb_surface_p target_surface = NULL;
   1362     psb_surface_p tmp = ctx->obj_context->current_render_target->psb_surface;
   1363     if (target_surface != tmp) { /* for field picture, only reset one time */
   1364         target_surface = tmp;
   1365 
   1366         int ret = psb_buffer_map(&target_surface->buf, &surface_data);
   1367         if (ret) {
   1368             goto out;
   1369         }
   1370         memset(surface_data, 0x33, target_surface->size);
   1371         psb_buffer_unmap(&target_surface->buf);
   1372     }
   1373 out:
   1374 #endif
   1375 
   1376     if (ctx->pic_params) {
   1377         free(ctx->pic_params);
   1378         ctx->pic_params = NULL;
   1379     }
   1380 
   1381     /* TODO: others */
   1382     return VA_STATUS_SUCCESS;
   1383 }
   1384 
   1385 
   1386 static VAStatus psb_MPEG2MC_RenderPicture(
   1387     object_context_p obj_context,
   1388     object_buffer_p *buffers,
   1389     int num_buffers)
   1390 {
   1391     int i;
   1392     INIT_CONTEXT_MPEG2MC;
   1393     VAStatus vaStatus = VA_STATUS_SUCCESS;
   1394 
   1395     ctx->mb_param = NULL; /* Init. compressed buffer pointers   */
   1396     ctx->residual_buf = NULL;
   1397 
   1398     for (i = 0; i < num_buffers; i++) {
   1399         object_buffer_p obj_buffer = buffers[i];
   1400 
   1401         switch (obj_buffer->type) {
   1402             /* Picture parameters processing */
   1403         case VAPictureParameterBufferType: {
   1404             vaStatus = psb__MPEG2MC_process_picture_param(ctx, obj_buffer);
   1405             DEBUG_FAILURE;
   1406             break;
   1407         }
   1408         /* Macroblock Data processing */
   1409         case VAMacroblockParameterBufferType: {
   1410             ctx->mb_param = (VAMacroblockParameterBufferMPEG2 *)obj_buffer->buffer_data;
   1411             ctx->mb_first_addr = ctx->mb_param->macroblock_address;
   1412             ctx->mb_in_buffer = obj_buffer->num_elements;
   1413             /* drv_debug_msg(VIDEO_DEBUG_GENERAL, "Macroblock count %d\n",ctx->mb_in_buffer); */
   1414             break;
   1415         }
   1416         /* Residual Difference Data processing */
   1417         case VAResidualDataBufferType: {
   1418             /* store the data after VLD+IDCT */
   1419             ctx->residual_buf = obj_buffer->psb_buffer;
   1420             ctx->blk_in_buffer = obj_buffer->num_elements;
   1421             break;
   1422         }
   1423         default:
   1424             drv_debug_msg(VIDEO_DEBUG_GENERAL, "Unhandled buffer type 0x%x\n", obj_buffer->type);
   1425             break;
   1426         }
   1427     }
   1428 
   1429     /* Assuming residual and MB control buffers have been located */
   1430     if (ctx->residual_buf && ctx->mb_param) {
   1431         ctx->residual_sent = 0;
   1432         ctx->residual_pendingDMA = 0;
   1433 
   1434         if (ctx->picture_coding_type == PICTURE_CODING_I) {
   1435             psb__MPEG2MC_process_mbs_intra(ctx);
   1436         } else {
   1437             psb__MPEG2MC_process_mbs_interPB(ctx);
   1438         }
   1439         ctx->mb_param = NULL;
   1440     }
   1441 
   1442     return VA_STATUS_SUCCESS;
   1443 }
   1444 
   1445 
   1446 static VAStatus psb_MPEG2MC_EndPicture(
   1447     object_context_p obj_context)
   1448 {
   1449     VAStatus vaStatus = VA_STATUS_SUCCESS;
   1450     INIT_CONTEXT_MPEG2MC;
   1451 
   1452     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psb_MPEG2MC_EndPicture\n");
   1453 
   1454     if (psb_context_flush_cmdbuf(ctx->obj_context)) {
   1455         vaStatus = VA_STATUS_ERROR_UNKNOWN;
   1456     }
   1457 
   1458     return vaStatus;
   1459 }
   1460 
   1461 /* TODO: integrate with VLD */
   1462 struct format_vtable_s psb_MPEG2MC_vtable = {
   1463 queryConfigAttributes:
   1464     psb_MPEG2MC_QueryConfigAttributes,
   1465 validateConfig:
   1466     psb_MPEG2MC_ValidateConfig,
   1467 createContext:
   1468     psb_MPEG2MC_CreateContext,
   1469 destroyContext:
   1470     psb_MPEG2MC_DestroyContext,
   1471 beginPicture:
   1472     psb_MPEG2MC_BeginPicture,
   1473 renderPicture:
   1474     psb_MPEG2MC_RenderPicture,
   1475 endPicture:
   1476     psb_MPEG2MC_EndPicture
   1477 };
   1478