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@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
66typedef 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
84static  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
92static  const uint32_t  ft_libva2msvdx[] = {0,/* Invalid picture type   */
93        0,/* Top field */
94        1,/* Bottom field */
95        2
96                                           };/* Frame picture     */
97
98
99struct 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
139typedef 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
144static 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
295typedef struct _PSB_MVvalue {
296    short  horz;
297    short  vert;
298} psb_MVvalue, *psb_MVvalue_p;
299
300#define MV_LIBVA2PSB(mb_param)                  \
301do {                                            \
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
315static 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. */
462static 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
537static 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
569static 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. */
585static 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
607static 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
640static 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
676static 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 picture’s address is at index 0. When decoding a B-picture the backward
721      reference picture’s 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.*/
759static 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.*/
845static 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
936static 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
1046static 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
1117static 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
1227static 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
1236static 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
1255static 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
1301static 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
1339static 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
1354static 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    }
1373out:
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
1386static 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
1446static 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 */
1462struct format_vtable_s psb_MPEG2MC_vtable = {
1463queryConfigAttributes:
1464    psb_MPEG2MC_QueryConfigAttributes,
1465validateConfig:
1466    psb_MPEG2MC_ValidateConfig,
1467createContext:
1468    psb_MPEG2MC_CreateContext,
1469destroyContext:
1470    psb_MPEG2MC_DestroyContext,
1471beginPicture:
1472    psb_MPEG2MC_BeginPicture,
1473renderPicture:
1474    psb_MPEG2MC_RenderPicture,
1475endPicture:
1476    psb_MPEG2MC_EndPicture
1477};
1478