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 
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 
psb__MPEG2MC_send_interPB_prediction(context_MPEG2MC_p ctx,psb_cmdbuf_p const cmdbuf,VAMacroblockParameterBufferMPEG2 * const mb_param,int second_pred)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 
psb__MPEG2MC_send_motion_vectores(context_MPEG2MC_p const ctx,psb_cmdbuf_p cmdbuf,VAMacroblockParameterBufferMPEG2 * const mb_param)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. */
psb__MPEG2MC_send_mb_number(context_MPEG2MC_p const ctx,psb_cmdbuf_p cmdbuf,const uint32_t mb_addr,const uint32_t motion_type,const eMB_CODE_TYPE MB_coding_type)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 
psb__MPEG2MC_finalise_residDMA(context_MPEG2MC_p const ctx)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 
psb__MPEG2MC_check_segment_residDMA(context_MPEG2MC_p const ctx,uint32_t min_space)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. */
psb__MPEG2MC_send_residual(context_MPEG2MC_p ctx,uint32_t pattern_code)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 
psb__MPEG2MC_send_slice_parameters(context_MPEG2MC_p const ctx)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 
psb__MPEG2MC_send_slice_picture_endcommand(context_MPEG2MC_p const ctx,int end_picture)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 
psb__MPEG2MC_send_highlevel_commands(context_MPEG2MC_p const ctx)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 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.*/
psb__MPEG2MC_interPB_mb(context_MPEG2MC_p const ctx,VAMacroblockParameterBufferMPEG2 * const mb_param)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.*/
psb__MPEG2MC_process_mbs_interPB(context_MPEG2MC_p const ctx)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 
psb__MPEG2MC_intra_mb(context_MPEG2MC_p const ctx,const VAMacroblockParameterBufferMPEG2 * const mb_param)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 
psb__MPEG2MC_process_mbs_intra(context_MPEG2MC_p const ctx)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 
psb__MPEG2MC_process_picture_param(context_MPEG2MC_p ctx,object_buffer_p obj_buffer)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 
psb_MPEG2MC_QueryConfigAttributes(VAProfile profile,VAEntrypoint entrypoint,VAConfigAttrib * attrib_list,int num_attribs)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 
psb_MPEG2MC_ValidateConfig(object_config_p obj_config)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 
psb__MPEG2MC_check_legal_picture(object_context_p obj_context,object_config_p obj_config)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 
psb_MPEG2MC_CreateContext(object_context_p obj_context,object_config_p obj_config)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 
psb_MPEG2MC_DestroyContext(object_context_p obj_context)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 
psb_MPEG2MC_BeginPicture(object_context_p obj_context)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 
psb_MPEG2MC_RenderPicture(object_context_p obj_context,object_buffer_p * buffers,int num_buffers)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 
psb_MPEG2MC_EndPicture(object_context_p obj_context)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