pnw_H264.c revision 29781ffb2cbf9fb72df9fc538c537690c3dd7cab
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 *    Waldo Bastian <waldo.bastian@intel.com>
27 *    Zeng Li <zeng.li@intel.com>
28 *
29 */
30
31#include "pnw_H264.h"
32#include "psb_def.h"
33#include "psb_drv_debug.h"
34#include "psb_surface.h"
35#include "psb_cmdbuf.h"
36#include "pnw_rotate.h"
37
38#include "hwdefs/reg_io2.h"
39#include "hwdefs/msvdx_offsets.h"
40#include "hwdefs/msvdx_cmds_io2.h"
41#include "hwdefs/msvdx_core_regs_io2.h"
42#include "hwdefs/msvdx_vec_reg_io2.h"
43#include "hwdefs/msvdx_vec_h264_reg_io2.h"
44#include "hwdefs/dxva_fw_ctrl.h"
45
46#include <stdlib.h>
47#include <stdint.h>
48#include <string.h>
49
50
51#define GET_SURFACE_INFO_is_used(psb_surface) ((int) (psb_surface->extra_info[0]))
52#define SET_SURFACE_INFO_is_used(psb_surface, val) psb_surface->extra_info[0] = (uint32_t) val;
53#define GET_SURFACE_INFO_col_pic_params(psb_surface) (psb_surface->extra_info[1])
54#define SET_SURFACE_INFO_col_pic_params(psb_surface, val) psb_surface->extra_info[1] = val;
55#define GET_SURFACE_INFO_dpb_idx(psb_surface) (psb_surface->extra_info[2])
56#define SET_SURFACE_INFO_dpb_idx(psb_surface, val) psb_surface->extra_info[2] = val;
57#define GET_SURFACE_INFO_colocated_index(psb_surface) ((int) (psb_surface->extra_info[3]))
58#define SET_SURFACE_INFO_colocated_index(psb_surface, val) psb_surface->extra_info[3] = (uint32_t) val;
59
60#define IS_USED_AS_REFERENCE(pic_flags)         ( pic_flags & (VA_PICTURE_H264_SHORT_TERM_REFERENCE | VA_PICTURE_H264_LONG_TERM_REFERENCE) )
61
62/* Truncates a signed integer to 17 bits */
63#define SIGNTRUNC( x ) ((( (x)  >> 15) & 0x10000) | ( (x) & 0xffff))
64
65#define MSVDX_VEC_REGS_BASE_MTX 0x0800
66#define MSVDX_COMMANDS_BASE_MTX 0x1000
67#define MSVDX_IQRAM_BASE_MTX    0x700
68
69#define SLICEDATA_BUFFER_TYPE(type) ((type==VASliceDataBufferType)?"VASliceDataBufferType":"VAProtectedSliceDataBufferType")
70
71typedef enum {
72    PICT_NONE,
73    PICT_FRAME,
74    PICT_TOP,
75    PICT_BOTTOM,
76    PICT_PAIR
77} PICTYPE;
78
79typedef enum {
80    H264_BASELINE_PROFILE = 0,
81    H264_MAIN_PROFILE = 1,
82    H264_HIGH_PROFILE = 2
83} PROFILE;
84
85static const char *profile2str[] = {
86    "H264_BASELINE_PROFILE",
87    "H264_MAIN_PROFILE",
88    "H264_HIGH_PROFILE"
89};
90
91typedef enum {
92    ST_P,
93    ST_B ,
94    ST_I ,
95    ST_SP ,
96    ST_SI
97} SLICE_TYPE;
98
99static IMG_UINT8 aSliceTypeVAtoMsvdx[] = { 1 , 2 , 0, 1, 0 };
100
101static const char *slice2str[] = {
102    "ST_P",
103    "ST_B",
104    "ST_I",
105    "ST_SP",
106    "ST_SI"
107};
108
109typedef enum {
110    DEBLOCK_NONE,
111    DEBLOCK_STD,
112    DEBLOCK_INTRA_OOLD
113} DEBLOCK_MODE_2NDPASS;
114
115struct context_H264_s {
116    object_context_p obj_context; /* back reference */
117
118    uint32_t profile; // ENTDEC BE_PROFILE & FE_PROFILE
119    uint32_t profile_idc; // BE_PROFILEIDC
120
121    /* Picture parameters */
122    VAPictureParameterBufferH264 *pic_params;
123    object_surface_p forward_ref_surface;
124    object_surface_p backward_ref_surface;
125
126    uint32_t coded_picture_width;    /* in pixels */
127    uint32_t coded_picture_height;    /* in pixels */
128
129    uint32_t picture_width_mb;        /* in macroblocks */
130    uint32_t picture_height_mb;        /* in macroblocks */
131    uint32_t size_mb;                /* in macroblocks */
132
133    uint32_t first_mb_x;
134    uint32_t first_mb_y;
135
136    uint32_t mb_width_c;                /* Chroma macroblock width */
137    uint32_t mb_height_c;               /* Chroma macroblock height */
138
139    uint32_t bit_depth_l;               /* Luma bit depth */
140    uint32_t qp_bd_offset_l;
141    uint32_t bit_depth_c;               /* Chroma bit depth */
142    uint32_t qp_bd_offset_c;
143
144    uint32_t raw_mb_bits;               /* Number of bits per macroblock */
145
146    uint32_t picture_width_samples_l;
147    uint32_t picture_height_samples_l;
148    uint32_t picture_width_samples_c;
149    uint32_t picture_height_samples_c;
150
151    uint32_t picture_height_map_units;
152    uint32_t picture_size_map_units;
153
154    PICTYPE pic_type;
155    uint32_t field_type;
156
157    uint32_t long_term_frame_flags;
158    uint32_t two_pass_mode;
159    uint32_t deblock_mode;
160    uint32_t slice_count;
161
162    /* Registers */
163    uint32_t reg_SPS0;
164    uint32_t reg_PPS0;
165    uint32_t reg_PIC0;
166
167    uint32_t slice0_params;
168    uint32_t slice1_params;
169
170    /* Split buffers */
171    int split_buffer_pending;
172
173    /* List of VASliceParameterBuffers */
174    object_buffer_p *slice_param_list;
175    int slice_param_list_size;
176    int slice_param_list_idx;
177
178    /* VLC packed data */
179    struct psb_buffer_s vlc_packed_table;
180
181    /* Preload buffer */
182    struct psb_buffer_s preload_buffer;
183
184    /* Slice Group Map buffer */
185    psb_buffer_p slice_group_map_buffer;
186
187    /* IQ matrix */
188    VAIQMatrixBufferH264 *iq_matrix;
189    VASliceParameterBufferH264 *slice_param;
190
191    /* Reference Cache */
192    struct psb_buffer_s reference_cache;
193
194    uint32_t *p_range_mapping_base0;
195    uint32_t *p_range_mapping_base1;
196    uint32_t *p_slice_params; /* pointer to ui32SliceParams in CMD_HEADER */
197    uint32_t *slice_first_pic_last;
198    uint32_t *alt_output_flags;
199
200    /* CoLocated buffers - aka ParamMemInfo */
201    struct psb_buffer_s *colocated_buffers;
202    int colocated_buffers_size;
203    int colocated_buffers_idx;
204};
205
206typedef struct context_H264_s *context_H264_p;
207
208#define INIT_CONTEXT_H264    context_H264_p ctx = (context_H264_p) obj_context->format_data;
209
210#define SURFACE(id)    ((object_surface_p) object_heap_lookup( &ctx->obj_context->driver_data->surface_heap, id ))
211
212#define CACHE_REF_OFFSET        72
213#define CACHE_ROW_OFFSET        4
214
215#define REFERENCE_CACHE_SIZE    (512 * 1024)
216
217#define MAX_PRELOAD_CMDS                                (40*2)
218typedef struct {
219    IMG_UINT8           ui8Address[MAX_PRELOAD_CMDS]; /* Address = (ui8Address << 1 | 0x400 ) */
220    IMG_UINT32          ui32Value[MAX_PRELOAD_CMDS];
221} ADDRDATA;
222
223typedef struct {
224    IMG_UINT32          ui32ContextId;
225    IMG_UINT32          ui32PreloadBufferSize;
226    ADDRDATA            aData;
227} PRELOAD;
228
229
230
231/* **************************************************************************************************************** */
232/* Prepacked H264 VLC Tables */
233/* **************************************************************************************************************** */
234static const IMG_UINT16 ui16H264VLCTableData[] = {
235    0x4000, 0x4205, 0x440a, 0x2204, 0x2206, 0x0208, 0x040b, 0x400f,
236    0x4204, 0x4209, 0x4013, 0x420e, 0x4217, 0x421b, 0x4212, 0x420d,
237    0x4208, 0x2a08, 0x0232, 0x0035, 0x0036, 0x441f, 0x4416, 0x4411,
238    0x440c, 0x0407, 0x040e, 0x0415, 0x041c, 0x0223, 0x4a35, 0x3a00,
239    0x4420, 0x4426, 0x4421, 0x441c, 0x442b, 0x4422, 0x441d, 0x4418,
240    0x4433, 0x442e, 0x4429, 0x4428, 0x442f, 0x442a, 0x4425, 0x4424,
241    0x443b, 0x4436, 0x4431, 0x4430, 0x4437, 0x4432, 0x442d, 0x442c,
242    0x4443, 0x443e, 0x443d, 0x4438, 0x443f, 0x443a, 0x4439, 0x4434,
243    0x4240, 0x4242, 0x4241, 0x423c, 0x4227, 0x421e, 0x4219, 0x4214,
244    0x4023, 0x401a, 0x4015, 0x4010, 0x0410, 0x0249, 0x024c, 0x004f,
245    0x4613, 0x460f, 0x440a, 0x440a, 0x4205, 0x4205, 0x4205, 0x4205,
246    0x4200, 0x4200, 0x4200, 0x4200, 0x2a08, 0x0231, 0x0034, 0x0035,
247    0x4423, 0x4416, 0x4415, 0x440c, 0x0407, 0x040e, 0x0415, 0x121c,
248    0x0222, 0x4a3f, 0x3a00, 0x442f, 0x4426, 0x4425, 0x4420, 0x442b,
249    0x4422, 0x4421, 0x441c, 0x442c, 0x442e, 0x442d, 0x4428, 0x4433,
250    0x442a, 0x4429, 0x4424, 0x443b, 0x4436, 0x4435, 0x4434, 0x4437,
251    0x4432, 0x4431, 0x4430, 0x0203, 0x423a, 0x4238, 0x423d, 0x423c,
252    0x423e, 0x4239, 0x4243, 0x4242, 0x4241, 0x4240, 0x4227, 0x421e,
253    0x421d, 0x4218, 0x4014, 0x401a, 0x4019, 0x4010, 0x421f, 0x4212,
254    0x4211, 0x4208, 0x421b, 0x420e, 0x420d, 0x4204, 0x4017, 0x4009,
255    0x2210, 0x0432, 0x0239, 0x023c, 0x600a, 0x6008, 0x003d, 0x003e,
256    0x461f, 0x461b, 0x4617, 0x4613, 0x460f, 0x460a, 0x4605, 0x4600,
257    0x0403, 0x040a, 0x0611, 0x4433, 0x442e, 0x4429, 0x4424, 0x442f,
258    0x442a, 0x4425, 0x4420, 0x4430, 0x4436, 0x4431, 0x442c, 0x4437,
259    0x4432, 0x442d, 0x4428, 0x3600, 0x4640, 0x4643, 0x4642, 0x4641,
260    0x463c, 0x463f, 0x463e, 0x463d, 0x4638, 0x463b, 0x463a, 0x4639,
261    0x4634, 0x4435, 0x4435, 0x441c, 0x4418, 0x4426, 0x4414, 0x442b,
262    0x4422, 0x4421, 0x4410, 0x420c, 0x421e, 0x421d, 0x4208, 0x4227,
263    0x421a, 0x4219, 0x4204, 0x400d, 0x4023, 0x400e, 0x4009, 0x2208,
264    0x5406, 0x540a, 0x540e, 0x5412, 0x5416, 0x541a, 0x541e, 0x5204,
265    0x0002, 0x5002, 0x3000, 0x4000, 0x4005, 0x4200, 0x440a, 0x0401,
266    0x1208, 0x000a, 0x4410, 0x440c, 0x4408, 0x440f, 0x4409, 0x4404,
267    0x4013, 0x4212, 0x4211, 0x400e, 0x400d, 0x4000, 0x4205, 0x440a,
268    0x0404, 0x480f, 0x4a13, 0x2609, 0x441b, 0x4417, 0x4412, 0x440e,
269    0x440d, 0x4409, 0x4408, 0x4404, 0x0205, 0x0208, 0x020b, 0x020e,
270    0x1411, 0x4216, 0x4211, 0x4210, 0x420c, 0x421f, 0x421a, 0x4215,
271    0x4214, 0x4223, 0x421e, 0x4219, 0x4218, 0x4222, 0x4221, 0x421d,
272    0x421c, 0x3400, 0x3400, 0x3400, 0x4420, 0x4000, 0x0006, 0x0007,
273    0x0008, 0x0009, 0x000a, 0x040b, 0x4002, 0x4001, 0x4004, 0x4003,
274    0x4006, 0x4005, 0x4008, 0x4007, 0x400a, 0x4009, 0x3400, 0x440f,
275    0x440e, 0x440d, 0x420c, 0x420c, 0x420b, 0x420b, 0x1208, 0x000e,
276    0x000f, 0x4404, 0x4403, 0x4402, 0x4401, 0x4400, 0x0203, 0x420a,
277    0x4209, 0x420e, 0x420d, 0x420c, 0x420b, 0x4008, 0x4007, 0x4006,
278    0x4005, 0x0208, 0x000d, 0x000e, 0x4407, 0x4406, 0x4403, 0x4402,
279    0x4401, 0x0004, 0x420c, 0x420a, 0x4209, 0x400d, 0x400b, 0x4008,
280    0x4005, 0x4004, 0x4000, 0x0208, 0x000b, 0x000c, 0x4408, 0x4406,
281    0x4405, 0x4404, 0x4401, 0x420c, 0x420b, 0x420a, 0x4200, 0x4009,
282    0x4007, 0x4003, 0x4002, 0x2208, 0x000a, 0x000b, 0x4407, 0x4406,
283    0x4405, 0x4404, 0x4403, 0x400a, 0x4209, 0x420b, 0x4008, 0x4002,
284    0x4001, 0x4000, 0x2408, 0x4409, 0x4407, 0x4406, 0x4405, 0x4404,
285    0x4403, 0x4402, 0x4008, 0x4201, 0x4400, 0x440a, 0x2408, 0x4408,
286    0x4406, 0x4404, 0x4403, 0x4402, 0x4205, 0x4205, 0x4007, 0x4201,
287    0x4400, 0x4409, 0x2604, 0x0008, 0x4205, 0x4204, 0x4007, 0x4201,
288    0x4402, 0x4600, 0x4608, 0x4006, 0x4003, 0x2604, 0x4206, 0x4204,
289    0x4203, 0x4005, 0x4202, 0x4407, 0x4600, 0x4601, 0x2404, 0x4205,
290    0x4204, 0x4203, 0x4002, 0x4206, 0x4400, 0x4401, 0x4004, 0x0003,
291    0x4402, 0x5000, 0x4003, 0x4005, 0x4003, 0x4202, 0x4404, 0x5000,
292    0x4002, 0x4203, 0x5000, 0x5000, 0x4002, 0x4000, 0x4001, 0x4000,
293    0x4201, 0x4402, 0x4403, 0x4000, 0x4201, 0x4202, 0x4001, 0x4000,
294    0x4001, 0x4000, 0x4000, 0x4201, 0x4202, 0x4203, 0x4202, 0x4201,
295    0x4200, 0x0004, 0x4202, 0x4201, 0x4200, 0x4004, 0x4003, 0x0203,
296    0x4201, 0x4200, 0x4205, 0x4204, 0x4203, 0x4202, 0x4401, 0x4402,
297    0x4404, 0x4403, 0x4406, 0x4405, 0x4200, 0x4200, 0x2a08, 0x4406,
298    0x4405, 0x4404, 0x4403, 0x4402, 0x4401, 0x4400, 0x4007, 0x4208,
299    0x4409, 0x460a, 0x480b, 0x4a0c, 0x2201, 0x400d, 0x420e, 0x3200,
300};
301
302/* Set bottom field flag in bit 7 and DPB index in bits 0:3 */
303static uint32_t PICTURE2INDEX(context_H264_p ctx, VAPictureH264 *pic)
304{
305    uint32_t result = 0xff; /* unused */
306    object_surface_p ref_surface = SURFACE(pic->picture_id);
307    if (ref_surface) {
308        result = GET_SURFACE_INFO_dpb_idx(ref_surface->psb_surface);
309    }
310    if (pic->flags & VA_PICTURE_H264_BOTTOM_FIELD) {
311        result |= 0x80; /* Set bit 7 */
312    }
313    return result;
314}
315
316static void pnw_H264_QueryConfigAttributes(
317    VAProfile profile,
318    VAEntrypoint entrypoint,
319    VAConfigAttrib *attrib_list,
320    int num_attribs)
321{
322    /* No H264 specific attributes */
323}
324
325static VAStatus pnw_H264_ValidateConfig(
326    object_config_p obj_config)
327{
328    int i;
329    /* Check all attributes */
330    for (i = 0; i < obj_config->attrib_count; i++) {
331        switch (obj_config->attrib_list[i].type) {
332        case VAConfigAttribRTFormat:
333            /* Ignore */
334            break;
335
336        default:
337            return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED;
338        }
339    }
340
341    return VA_STATUS_SUCCESS;
342}
343
344static VAStatus psb__H264_check_legal_picture(object_context_p obj_context, object_config_p obj_config)
345{
346    VAStatus vaStatus = VA_STATUS_SUCCESS;
347
348    if (NULL == obj_context) {
349        vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT;
350        DEBUG_FAILURE;
351        return vaStatus;
352    }
353
354    if (NULL == obj_config) {
355        vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
356        DEBUG_FAILURE;
357        return vaStatus;
358    }
359
360    /* MSVDX decode capability for H.264:
361     *     BP@L3
362     *     MP@L4.1
363     *     HP@L4.1
364     *
365     * Refer to Table A-6 (Maximum frame rates for some example frame sizes) of ISO/IEC 14496-10:2005 (E).
366     */
367    switch (obj_config->profile) {
368    case VAProfileH264Baseline:
369        if ((obj_context->picture_width <= 0) || (obj_context->picture_width > 720)
370            || (obj_context->picture_height <= 0) || (obj_context->picture_height > 576)) {
371            vaStatus = VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED;
372        }
373        break;
374
375    case VAProfileH264Main:
376    case VAProfileH264High:
377    case VAProfileH264ConstrainedBaseline:
378        if ((obj_context->picture_width <= 0) || (obj_context->picture_width > 1920)
379            || (obj_context->picture_height <= 0) || (obj_context->picture_height > 1088)) {
380            vaStatus = VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED;
381        }
382        break;
383
384    default:
385        vaStatus = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
386        break;
387    }
388
389    return vaStatus;
390}
391
392static void pnw_H264_DestroyContext(object_context_p obj_context);
393
394static VAStatus pnw_H264_CreateContext(
395    object_context_p obj_context,
396    object_config_p obj_config)
397{
398    VAStatus vaStatus = VA_STATUS_SUCCESS;
399    context_H264_p ctx;
400    /* Validate flag */
401    /* Validate picture dimensions */
402    //vaStatus = psb__H264_check_legal_picture(obj_context, obj_config);
403    if (VA_STATUS_SUCCESS != vaStatus) {
404        DEBUG_FAILURE;
405        return vaStatus;
406    }
407
408    ctx = (context_H264_p) calloc(1, sizeof(struct context_H264_s));
409    if (NULL == ctx) {
410        vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
411        DEBUG_FAILURE;
412        return vaStatus;
413    }
414    obj_context->format_data = (void*) ctx;
415    ctx->obj_context = obj_context;
416    ctx->pic_params = NULL;
417
418    ctx->split_buffer_pending = FALSE;
419
420    ctx->slice_param_list_size = 8;
421    ctx->slice_param_list = (object_buffer_p*) calloc(1, sizeof(object_buffer_p) * ctx->slice_param_list_size);
422    ctx->slice_param_list_idx = 0;
423
424    if (NULL == ctx->slice_param_list) {
425        vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
426        DEBUG_FAILURE;
427        free(ctx);
428        return vaStatus;
429    }
430
431    ctx->colocated_buffers_size = obj_context->num_render_targets;
432    ctx->colocated_buffers_idx = 0;
433    ctx->colocated_buffers = (psb_buffer_p) calloc(1, sizeof(struct psb_buffer_s) * ctx->colocated_buffers_size);
434    if (NULL == ctx->colocated_buffers) {
435        vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
436        DEBUG_FAILURE;
437        free(ctx->slice_param_list);
438        free(ctx);
439        return vaStatus;
440    }
441
442    switch (obj_config->profile) {
443    case VAProfileH264Baseline:
444        ctx->profile = H264_BASELINE_PROFILE;
445        ctx->profile_idc = 0;
446        break;
447
448    case VAProfileH264Main:
449        ctx->profile = H264_MAIN_PROFILE;
450        ctx->profile_idc = 1;
451        break;
452
453    case VAProfileH264High:
454    case VAProfileH264ConstrainedBaseline:
455        ctx->profile = H264_HIGH_PROFILE;
456        ctx->profile_idc = 3;
457        break;
458
459    default:
460        ASSERT(0);
461        vaStatus = VA_STATUS_ERROR_UNKNOWN;
462    }
463
464
465    // TODO
466    if (vaStatus == VA_STATUS_SUCCESS) {
467        vaStatus = psb_buffer_create(obj_context->driver_data,
468                                     sizeof(PRELOAD),
469                                     psb_bt_vpu_only,
470                                     &ctx->preload_buffer);
471        DEBUG_FAILURE;
472    }
473
474    if (vaStatus == VA_STATUS_SUCCESS) {
475        vaStatus = psb_buffer_create(obj_context->driver_data,
476                                     REFERENCE_CACHE_SIZE,
477                                     psb_bt_vpu_only,
478                                     &ctx->reference_cache);
479        DEBUG_FAILURE;
480    }
481
482    if (vaStatus == VA_STATUS_SUCCESS) {
483        vaStatus = psb_buffer_create(obj_context->driver_data,
484                                     sizeof(ui16H264VLCTableData),
485                                     psb_bt_cpu_vpu,
486                                     &ctx->vlc_packed_table);
487        DEBUG_FAILURE;
488    }
489    if (vaStatus == VA_STATUS_SUCCESS) {
490        unsigned char *vlc_packed_data_address;
491        if (0 ==  psb_buffer_map(&ctx->vlc_packed_table, &vlc_packed_data_address)) {
492            memcpy(vlc_packed_data_address, ui16H264VLCTableData, sizeof(ui16H264VLCTableData));
493            psb_buffer_unmap(&ctx->vlc_packed_table);
494        } else {
495            vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
496            DEBUG_FAILURE;
497        }
498    }
499
500    if (vaStatus != VA_STATUS_SUCCESS) {
501        pnw_H264_DestroyContext(obj_context);
502    }
503
504    return vaStatus;
505}
506
507static void pnw_H264_DestroyContext(
508    object_context_p obj_context)
509{
510    INIT_CONTEXT_H264
511    int i;
512
513    psb_buffer_destroy(&ctx->reference_cache);
514    psb_buffer_destroy(&ctx->preload_buffer);
515    psb_buffer_destroy(&ctx->vlc_packed_table);
516
517    if (ctx->pic_params) {
518        free(ctx->pic_params);
519        ctx->pic_params = NULL;
520    }
521    if (ctx->iq_matrix) {
522        free(ctx->iq_matrix);
523        ctx->iq_matrix = NULL;
524    }
525
526    if (ctx->slice_param_list) {
527        free(ctx->slice_param_list);
528        ctx->slice_param_list = NULL;
529    }
530
531    if (ctx->colocated_buffers) {
532        for (i = 0; i < ctx->colocated_buffers_idx; ++i)
533            psb_buffer_destroy(&(ctx->colocated_buffers[i]));
534
535        free(ctx->colocated_buffers);
536        ctx->colocated_buffers = NULL;
537    }
538
539    free(obj_context->format_data);
540    obj_context->format_data = NULL;
541}
542
543static VAStatus psb__H264_allocate_colocated_buffer(context_H264_p ctx, object_surface_p obj_surface, uint32_t size)
544{
545    psb_buffer_p buf;
546    VAStatus vaStatus;
547    psb_surface_p surface = obj_surface->psb_surface;
548    int index = GET_SURFACE_INFO_colocated_index(surface);
549
550    if (!index) {
551        index = ctx->colocated_buffers_idx;
552        if (index >= ctx->colocated_buffers_size) {
553            return VA_STATUS_ERROR_UNKNOWN;
554        }
555
556        drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_H264: Allocating colocated buffer for surface %08x size = %08x\n", surface, size);
557
558        buf = &(ctx->colocated_buffers[index]);
559        vaStatus = psb_buffer_create(ctx->obj_context->driver_data, size, psb_bt_vpu_only, buf);
560        if (VA_STATUS_SUCCESS != vaStatus) {
561            return vaStatus;
562        }
563        ctx->colocated_buffers_idx++;
564        SET_SURFACE_INFO_colocated_index(surface, index + 1); /* 0 means unset, index is offset by 1 */
565    } else {
566        buf = &(ctx->colocated_buffers[index - 1]);
567        if (buf->size < size) {
568            psb_buffer_destroy(buf);
569            vaStatus = psb_buffer_create(ctx->obj_context->driver_data, size, psb_bt_vpu_only, buf);
570            if (VA_STATUS_SUCCESS != vaStatus) {
571                return vaStatus;
572            }
573            SET_SURFACE_INFO_colocated_index(surface, index); /* replace the original buffer */
574        }
575	}
576    return VA_STATUS_SUCCESS;
577}
578
579static psb_buffer_p psb__H264_lookup_colocated_buffer(context_H264_p ctx, psb_surface_p surface)
580{
581    drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_H264: Looking up colocated buffer for surface %08x\n", surface);
582    int index = GET_SURFACE_INFO_colocated_index(surface);
583    if (!index) {
584        return NULL;
585    }
586    return &(ctx->colocated_buffers[index-1]); /* 0 means unset, index is offset by 1 */
587}
588
589#define P(x)    psb__trace_message("PARAMS: " #x "\t= %08x (%d)\n", p->x, p->x)
590static void psb__H264_trace_pic_params(VAPictureParameterBufferH264 *p)
591{
592    P(CurrPic);
593    P(picture_width_in_mbs_minus1);
594    P(picture_height_in_mbs_minus1);
595    P(bit_depth_luma_minus8);
596    P(bit_depth_chroma_minus8);
597    P(num_ref_frames);
598    P(seq_fields);
599    P(num_slice_groups_minus1);
600    P(slice_group_map_type);
601    P(pic_init_qp_minus26);
602    P(chroma_qp_index_offset);
603    P(second_chroma_qp_index_offset);
604    P(pic_fields);
605    P(frame_num);
606}
607
608static VAStatus psb__H264_process_picture_param(context_H264_p ctx, object_buffer_p obj_buffer)
609{
610    psb_surface_p target_surface = ctx->obj_context->current_render_target->psb_surface;
611    uint32_t reg_value;
612    VAStatus vaStatus;
613
614    ASSERT(obj_buffer->type == VAPictureParameterBufferType);
615    ASSERT(obj_buffer->num_elements == 1);
616    ASSERT(obj_buffer->size == sizeof(VAPictureParameterBufferH264));
617    ASSERT(target_surface);
618
619    if ((obj_buffer->num_elements != 1) ||
620        (obj_buffer->size != sizeof(VAPictureParameterBufferH264)) ||
621        (NULL == target_surface)) {
622        return VA_STATUS_ERROR_UNKNOWN;
623    }
624
625    /* Transfer ownership of VAPictureParameterBufferH264 data */
626    VAPictureParameterBufferH264 *pic_params = (VAPictureParameterBufferH264 *) obj_buffer->buffer_data;
627    if (ctx->pic_params) {
628        free(ctx->pic_params);
629    }
630    ctx->pic_params = pic_params;
631    obj_buffer->buffer_data = NULL;
632    obj_buffer->size = 0;
633
634    if (psb_video_trace_fp && (psb_video_trace_level & VABUF_TRACE))
635        psb__H264_trace_pic_params(pic_params);
636
637    /* Table 6-1 */
638    uint32_t sub_width_c  = (pic_params->seq_fields.bits.chroma_format_idc > 2) ? 1 : 2;
639    uint32_t sub_height_c = (pic_params->seq_fields.bits.chroma_format_idc > 1) ? 1 : 2;
640
641    if (pic_params->seq_fields.bits.chroma_format_idc == 0) {
642        ctx->mb_width_c = 0;
643        ctx->mb_height_c = 0;
644    } else {
645        ctx->mb_width_c = 16 / sub_width_c;             /* 6-1 */
646        ctx->mb_height_c = 16 / sub_height_c;           /* 6-2 */
647    }
648
649    ctx->bit_depth_l = 8 + pic_params->bit_depth_luma_minus8;                   /* (7-1) */
650    ctx->qp_bd_offset_l = 6 * pic_params->bit_depth_luma_minus8;                /* (7-2) */
651
652    ctx->bit_depth_c = 8 + pic_params->bit_depth_chroma_minus8;                 /* (7-3) */
653    ctx->qp_bd_offset_c = 6 * (pic_params->bit_depth_chroma_minus8 + pic_params->seq_fields.bits.residual_colour_transform_flag);       /* (7-4) */
654
655    ctx->picture_width_mb = pic_params->picture_width_in_mbs_minus1 + 1;
656    ctx->picture_height_mb = pic_params->picture_height_in_mbs_minus1 + 1;
657
658    ctx->size_mb = ctx->picture_width_mb * ctx->picture_height_mb;              /* (7-25) */
659
660    //uint32_t colocated_size = (ctx->picture_width_mb + extra_size) * (ctx->picture_height_mb + extra_size) * 192;
661    uint32_t colocated_size = ((ctx->size_mb + 100) * 128 + 0xfff) & ~0xfff;
662
663    vaStatus = psb__H264_allocate_colocated_buffer(ctx, ctx->obj_context->current_render_target, colocated_size);
664    if (VA_STATUS_SUCCESS != vaStatus) {
665        DEBUG_FAILURE;
666        return vaStatus;
667    }
668
669    ctx->raw_mb_bits = 256 * ctx->bit_depth_l + 2 * ctx->mb_width_c * ctx->mb_height_c * ctx->bit_depth_c;      /* (7-5) */
670
671    ctx->picture_width_samples_l = ctx->picture_width_mb * 16;
672    ctx->picture_width_samples_c = ctx->picture_width_mb * ctx->mb_width_c;
673
674    ctx->picture_height_samples_l = ctx->picture_height_mb * 16;
675    ctx->picture_height_samples_c = ctx->picture_height_mb * ctx->mb_height_c;
676
677    // BECAUSE OF
678    //  sps->FrameHeightInMbs   = ( 2 - sps->seq_fields.bits.frame_mbs_only_flag ) * sps->PicHeightInMapUnits;  /* (7-15) */
679    ctx->picture_height_map_units = 1 + ctx->picture_height_mb / (2 - pic_params->seq_fields.bits.frame_mbs_only_flag);
680    ctx->picture_size_map_units = ctx->picture_width_mb * ctx->picture_height_map_units;/* (7-14) */
681
682    /* record just what type of picture we are */
683    if (pic_params->pic_fields.bits.field_pic_flag) {
684        if (pic_params->CurrPic.flags & VA_PICTURE_H264_BOTTOM_FIELD) {
685            ctx->pic_type = PICT_BOTTOM;
686            ctx->field_type = 1;
687        } else {
688            ctx->pic_type = PICT_TOP;
689            ctx->field_type = 0;
690        }
691    } else {
692        ctx->pic_type = PICT_FRAME;
693        ctx->field_type = pic_params->seq_fields.bits.mb_adaptive_frame_field_flag ? 3 : 2;
694    }
695
696    uint32_t i;
697    ctx->long_term_frame_flags = 0;
698    /* We go from high to low so that we are left with the lowest index */
699    for (i = pic_params->num_ref_frames; i--;) {
700        object_surface_p ref_surface = SURFACE(pic_params->ReferenceFrames[i].picture_id);
701        if (pic_params->ReferenceFrames[i].flags & VA_PICTURE_H264_BOTTOM_FIELD) {
702            ctx->long_term_frame_flags |= 0x01 << i;
703        }
704        if (ref_surface) {
705            SET_SURFACE_INFO_dpb_idx(ref_surface->psb_surface, i);
706        }
707    }
708
709    /* If the MB are not guarenteed to be consecutive - we must do a 2pass */
710    ctx->two_pass_mode = (pic_params->num_slice_groups_minus1 > 0) && (!ctx->pic_params->seq_fields.bits.mb_adaptive_frame_field_flag);
711
712    ctx->reg_SPS0 = 0;
713    REGIO_WRITE_FIELD_LITE(ctx->reg_SPS0, MSVDX_VEC_H264, CR_VEC_H264_BE_SPS0, H264_BE_SPS0_DEFAULT_MATRIX_FLAG, (ctx->profile == H264_BASELINE_PROFILE));    /* Always use suplied matrix non baseline otherwise use default*/
714    REGIO_WRITE_FIELD_LITE(ctx->reg_SPS0, MSVDX_VEC_H264, CR_VEC_H264_BE_SPS0, H264_BE_SPS0_2PASS_FLAG,         ctx->two_pass_mode);                    /* Always 0 for VA - we cant handle otherwise yet */
715    /* Assume SGM_8BIT */
716    REGIO_WRITE_FIELD_LITE(ctx->reg_SPS0, MSVDX_VEC_H264, CR_VEC_H264_FE_SPS0, H264_FE_SPS0_4BIT_SGM_FLAG,      0);
717    REGIO_WRITE_FIELD_LITE(ctx->reg_SPS0, MSVDX_VEC_H264, CR_VEC_H264_BE_SPS0, BE_PROFILEIDC,                   ctx->profile_idc);
718    REGIO_WRITE_FIELD_LITE(ctx->reg_SPS0, MSVDX_VEC_H264, CR_VEC_H264_FE_SPS0, MIN_LUMA_BIPRED_SIZE_8X8, (ctx->picture_width_mb > 80));
719    REGIO_WRITE_FIELD_LITE(ctx->reg_SPS0, MSVDX_VEC_H264, CR_VEC_H264_FE_SPS0, DIRECT_8X8_INFERENCE_FLAG,       pic_params->seq_fields.bits.direct_8x8_inference_flag);
720    REGIO_WRITE_FIELD_LITE(ctx->reg_SPS0, MSVDX_VEC_H264, CR_VEC_H264_FE_SPS0, CHROMA_FORMAT_IDC,               pic_params->seq_fields.bits.chroma_format_idc);
721    REGIO_WRITE_FIELD_LITE(ctx->reg_SPS0, MSVDX_VEC_H264, CR_VEC_H264_FE_SPS0, FRAME_MBS_ONLY_FLAG,             pic_params->seq_fields.bits.frame_mbs_only_flag);
722    REGIO_WRITE_FIELD_LITE(ctx->reg_SPS0, MSVDX_VEC_H264, CR_VEC_H264_FE_SPS0, PICWIDTHINMBSLESS1,              ctx->picture_width_mb - 1);
723
724    ctx->reg_PPS0 = 0;
725    REGIO_WRITE_FIELD_LITE(ctx->reg_PPS0, MSVDX_VEC_H264, CR_VEC_H264_FE_PPS0, TRANSFORM_8X8_MODE_FLAG,         pic_params->pic_fields.bits.transform_8x8_mode_flag);
726    REGIO_WRITE_FIELD_LITE(ctx->reg_PPS0, MSVDX_VEC_H264, CR_VEC_H264_FE_PPS0, CONSTRAINED_INTRA_PRED_FLAG,     pic_params->pic_fields.bits.constrained_intra_pred_flag);
727    REGIO_WRITE_FIELD_LITE(ctx->reg_PPS0, MSVDX_VEC_H264, CR_VEC_H264_FE_PPS0, ENTROPY_CODING_MODE_FLAG,        pic_params->pic_fields.bits.entropy_coding_mode_flag);
728    REGIO_WRITE_FIELD_LITE(ctx->reg_PPS0, MSVDX_VEC_H264, CR_VEC_H264_FE_PPS0, NUM_SLICE_GROUPS_MINUS1,         pic_params->num_slice_groups_minus1);
729    REGIO_WRITE_FIELD_LITE(ctx->reg_PPS0, MSVDX_VEC_H264, CR_VEC_H264_BE_PPS0, BE_WEIGHTED_BIPRED_IDC,          pic_params->pic_fields.bits.weighted_bipred_idc);
730    REGIO_WRITE_FIELD_MASKEDLITE(ctx->reg_PPS0, MSVDX_VEC_H264, CR_VEC_H264_BE_PPS0, BE_CHROMA_QP_INDEX_OFFSET, pic_params->chroma_qp_index_offset);
731    REGIO_WRITE_FIELD_MASKEDLITE(ctx->reg_PPS0, MSVDX_VEC_H264, CR_VEC_H264_BE_PPS0, BE_SECOND_CHROMA_QP_INDEX_OFFSET,  pic_params->second_chroma_qp_index_offset);
732
733    uint32_t PicHeightInMbs     = ctx->picture_height_mb >> pic_params->pic_fields.bits.field_pic_flag;         /* (7-23) */
734    uint32_t PicSizeInMbs       = ctx->picture_width_mb * PicHeightInMbs;                       /* (7-26) */
735
736    ctx->reg_PIC0 = 0;
737    REGIO_WRITE_FIELD_LITE(ctx->reg_PIC0, MSVDX_VEC_H264, CR_VEC_H264_FE_CUR_PIC0, PICSIZEINMBSLESS1,           PicSizeInMbs - 1);
738    REGIO_WRITE_FIELD_LITE(ctx->reg_PIC0, MSVDX_VEC_H264, CR_VEC_H264_FE_CUR_PIC0, PICHEIGHTINMBSLESS1,         PicHeightInMbs - 1);
739    /* TODO */
740    REGIO_WRITE_FIELD_LITE(ctx->reg_PIC0, MSVDX_VEC_H264, CR_VEC_H264_BE_CUR_PIC0, BE_REFERENCE_FLAG,           IS_USED_AS_REFERENCE(pic_params->CurrPic.flags) ? 1 : 0);
741    REGIO_WRITE_FIELD_LITE(ctx->reg_PIC0, MSVDX_VEC_H264, CR_VEC_H264_FE_CUR_PIC0, MBAFFFRAMEFLAG,              pic_params->seq_fields.bits.mb_adaptive_frame_field_flag);
742    REGIO_WRITE_FIELD_LITE(ctx->reg_PIC0, MSVDX_VEC_H264, CR_VEC_H264_FE_CUR_PIC0, FIELD_PIC_FLAG,              pic_params->pic_fields.bits.field_pic_flag);
743    REGIO_WRITE_FIELD_LITE(ctx->reg_PIC0, MSVDX_VEC_H264, CR_VEC_H264_FE_CUR_PIC0, BOTTOM_FIELD_FLAG,           pic_params->CurrPic.flags & VA_PICTURE_H264_BOTTOM_FIELD ? 1 : 0);
744
745    /* Record some info about current picture */
746    reg_value = 0;
747    REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_H264, CR_VEC_H264_BE_COL_PIC0, COL_NOTFRAMEFLAG, (PICT_FRAME != ctx->pic_type) ? 1 : 0);
748    REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_H264, CR_VEC_H264_BE_COL_PIC0, COL_MBAFFFRAMEFLAG, pic_params->seq_fields.bits.mb_adaptive_frame_field_flag);
749    SET_SURFACE_INFO_col_pic_params(target_surface, reg_value);
750
751    if (pic_params->seq_fields.bits.chroma_format_idc == 0) {
752        vaStatus = psb_surface_set_chroma(target_surface, 128);
753        if (VA_STATUS_SUCCESS != vaStatus) {
754            DEBUG_FAILURE;
755            return vaStatus;
756        }
757    }
758
759    psb_CheckInterlaceRotate(ctx->obj_context, (unsigned char *)pic_params);
760
761
762#ifdef PSBVIDEO_MSVDX_EC
763    /* tell the driver to save the frame info for Error Concealment */
764    /*
765    if (driver_data->ec_enabled) {
766        psb_context_get_next_cmdbuf(ctx->obj_context);
767        psb_context_submit_frame_info(ctx->obj_context, &target_surface->buf,
768                                      target_surface->stride, target_surface->size,
769                                      ctx->picture_width_mb, ctx->size_mb);
770    }
771    */
772#endif
773
774    return VA_STATUS_SUCCESS;
775}
776
777static VAStatus psb__H264_process_iq_matrix(context_H264_p ctx, object_buffer_p obj_buffer)
778{
779    ASSERT(obj_buffer->type == VAIQMatrixBufferType);
780    ASSERT(obj_buffer->num_elements == 1);
781    ASSERT(obj_buffer->size == sizeof(VAIQMatrixBufferH264));
782
783    if ((obj_buffer->num_elements != 1) ||
784        (obj_buffer->size != sizeof(VAIQMatrixBufferH264))) {
785        return VA_STATUS_ERROR_UNKNOWN;
786    }
787
788    /* Transfer ownership of VAIQMatrixBufferH264 data */
789    if (ctx->iq_matrix) {
790        free(ctx->iq_matrix);
791    }
792    ctx->iq_matrix = (VAIQMatrixBufferH264 *) obj_buffer->buffer_data;
793    obj_buffer->buffer_data = NULL;
794    obj_buffer->size = 0;
795
796    return VA_STATUS_SUCCESS;
797}
798
799static VAStatus psb__H264_process_slice_group_map(context_H264_p ctx, object_buffer_p obj_buffer)
800{
801    ASSERT(obj_buffer->type == VASliceGroupMapBufferType);
802    ASSERT(obj_buffer->num_elements == 1);
803//    ASSERT(obj_buffer->size == ...);
804
805    if (obj_buffer->num_elements != 1) {
806        return VA_STATUS_ERROR_UNKNOWN;
807    }
808
809    ctx->slice_group_map_buffer = obj_buffer->psb_buffer;
810
811    return VA_STATUS_SUCCESS;
812}
813
814#define SCALING_LIST_4x4_SIZE   ((4*4))
815#define SCALING_LIST_8x8_SIZE   ((8*8))
816
817static void psb__H264_build_SCA_chunk(context_H264_p ctx)
818{
819    VAIQMatrixBufferH264 dummy_iq_matrix;
820    psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf;
821
822    VAIQMatrixBufferH264 *iq_matrix = ctx->iq_matrix;
823
824    if (!iq_matrix) {
825        drv_debug_msg(VIDEO_DEBUG_GENERAL, "H264: No IQ matrix received for frame. Sending dummy IQ matrix.\n");
826        iq_matrix = &dummy_iq_matrix;
827        memset(iq_matrix, 0, sizeof(VAIQMatrixBufferH264));
828    }
829
830    psb_cmdbuf_rendec_start(cmdbuf, REG_MSVDX_VEC_IQRAM_OFFSET);
831
832    /* 8x8 Inter Y */
833    psb_cmdbuf_rendec_write_block(cmdbuf, iq_matrix->ScalingList8x8[1], SCALING_LIST_8x8_SIZE);
834
835    /* 8x8 Intra Y */
836    psb_cmdbuf_rendec_write_block(cmdbuf, iq_matrix->ScalingList8x8[0], SCALING_LIST_8x8_SIZE);
837
838    /* 4x4 Intra Y */
839    psb_cmdbuf_rendec_write_block(cmdbuf, iq_matrix->ScalingList4x4[0], SCALING_LIST_4x4_SIZE);
840
841    /* 4x4 Inter Y */
842    psb_cmdbuf_rendec_write_block(cmdbuf, iq_matrix->ScalingList4x4[3], SCALING_LIST_4x4_SIZE);
843
844    /* 4x4 Inter Cb */
845    psb_cmdbuf_rendec_write_block(cmdbuf, iq_matrix->ScalingList4x4[4], SCALING_LIST_4x4_SIZE);
846
847    /* 4x4 Intra Cb */
848    psb_cmdbuf_rendec_write_block(cmdbuf, iq_matrix->ScalingList4x4[1], SCALING_LIST_4x4_SIZE);
849
850    /* 4x4 Inter Cr */
851    psb_cmdbuf_rendec_write_block(cmdbuf, iq_matrix->ScalingList4x4[5], SCALING_LIST_4x4_SIZE);
852
853    /* 4x4 Intra Cr */
854    psb_cmdbuf_rendec_write_block(cmdbuf, iq_matrix->ScalingList4x4[2], SCALING_LIST_4x4_SIZE);
855
856    psb_cmdbuf_rendec_end(cmdbuf);
857}
858
859static void psb__H264_build_picture_order_chunk(context_H264_p ctx)
860{
861    psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf;
862    VAPictureParameterBufferH264 *pic_params = ctx->pic_params;
863    uint32_t reg_value;
864    int i;
865
866    /* CHUNK: POC */
867    /* send Picture Order Counts (b frame only?) */
868    /* maybe need a state variable to track if this has already been sent for the frame */
869    psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_VEC, H264_CR_VEC_H264_BE_FOC0));
870
871    reg_value = 0;
872    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_H264, CR_VEC_H264_BE_FOC0, TOPFIELDORDERCNT_CURR,
873                           SIGNTRUNC(pic_params->CurrPic.TopFieldOrderCnt));
874    psb_cmdbuf_rendec_write(cmdbuf, reg_value);
875
876    reg_value = 0;
877    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_H264, CR_VEC_H264_BE_FOC1, BOTTOMFIELDORDERCNT_CURR,
878                           SIGNTRUNC(pic_params->CurrPic.BottomFieldOrderCnt));
879    psb_cmdbuf_rendec_write(cmdbuf, reg_value);
880
881    if (pic_params->num_ref_frames > 16) {
882        drv_debug_msg(VIDEO_DEBUG_ERROR, "Invalid reference number %d, set to 16\n", pic_params->num_ref_frames);
883        pic_params->num_ref_frames = 16;
884    }
885
886    for (i = 0; i < pic_params->num_ref_frames; i++) {
887        reg_value = 0;
888        REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_H264, CR_VEC_H264_BE_TOP_FOC, TOPFIELDORDERCNT,
889                               SIGNTRUNC(pic_params->ReferenceFrames[i].TopFieldOrderCnt));
890        psb_cmdbuf_rendec_write(cmdbuf, reg_value);
891
892        reg_value = 0;
893        REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_H264, CR_VEC_H264_BE_BOT_FOC, BOTTOMFIELDORDERCNT,
894                               SIGNTRUNC(pic_params->ReferenceFrames[i].BottomFieldOrderCnt));
895        psb_cmdbuf_rendec_write(cmdbuf, reg_value);
896    }
897
898    psb_cmdbuf_rendec_end(cmdbuf);
899}
900
901static void psb__H264_build_B_slice_chunk(context_H264_p ctx, VASliceParameterBufferH264 *slice_param)
902{
903    psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf;
904    VAPictureParameterBufferH264 *pic_params = ctx->pic_params;
905    uint32_t reg_value;
906    int i;
907
908    psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_VEC, H264_CR_VEC_H264_BE_COL_PIC0));
909
910    /* Colocated picture is picture 0 in list 1*/
911    object_surface_p colocated_surface = SURFACE(slice_param->RefPicList1[0].picture_id);
912    if (colocated_surface) {
913        uint32_t bottom_field_flag;
914        if (pic_params->pic_fields.bits.field_pic_flag) {
915            bottom_field_flag  = (slice_param->RefPicList1[0].flags & VA_PICTURE_H264_BOTTOM_FIELD) ? 1 : 0;
916        } else {
917            /* when current pic is a frame col bottom field flag is different */
918            IMG_INT32   i32Cur;
919            IMG_INT32   i32Top, i32Bot;
920            IMG_INT32   i32TopAbsDiffPoc, i32BotAbsDiffPoc;
921
922            /* current pic */
923            i32Top = pic_params->CurrPic.TopFieldOrderCnt;
924            i32Bot = pic_params->CurrPic.BottomFieldOrderCnt;
925            i32Cur = (i32Top < i32Bot) ? i32Top : i32Bot;
926
927            /* col pic */
928            i32Top = slice_param->RefPicList1[0].TopFieldOrderCnt;
929            i32Bot = slice_param->RefPicList1[0].BottomFieldOrderCnt;
930
931            i32TopAbsDiffPoc = (i32Cur < i32Top) ? i32Top - i32Cur : i32Cur - i32Top;
932            i32BotAbsDiffPoc = (i32Cur < i32Bot) ? i32Bot - i32Cur : i32Cur - i32Bot;
933
934            bottom_field_flag = (i32TopAbsDiffPoc < i32BotAbsDiffPoc) ? 0 : 1;
935        }
936
937        reg_value = GET_SURFACE_INFO_col_pic_params(colocated_surface->psb_surface);
938        REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_H264, CR_VEC_H264_BE_COL_PIC0, COL_BOTTOM_FIELD_FLAG, bottom_field_flag);
939        psb_cmdbuf_rendec_write(cmdbuf, reg_value);
940
941        psb_buffer_p colocated_target_buffer = psb__H264_lookup_colocated_buffer(ctx, colocated_surface->psb_surface);
942        ASSERT(colocated_target_buffer);
943        if (colocated_target_buffer) {
944            psb_cmdbuf_rendec_write_address(cmdbuf, colocated_target_buffer, 0);
945        } else {
946            /* This is an error */
947            psb_cmdbuf_rendec_write(cmdbuf, 0);
948        }
949    } else {
950        /* Need some better error handling here */
951        psb_cmdbuf_rendec_write(cmdbuf, 0);
952        psb_cmdbuf_rendec_write(cmdbuf, 0xDEADBEEF);
953    }
954
955    /* Calculate inverse index for reference pictures */
956    {
957        IMG_UINT8 list0_inverse[32];
958        memset(list0_inverse, 0xff, 32); /* Unused entries get 0xff */
959
960        if (slice_param->num_ref_idx_l0_active_minus1 + 1 > 32) {
961            drv_debug_msg(VIDEO_DEBUG_ERROR, "num_ref_idx_l0_active_minus1(%d) is too big. Set it with 31\n",
962                               slice_param->num_ref_idx_l0_active_minus1);
963            slice_param->num_ref_idx_l0_active_minus1 = 31;
964        }
965
966        if (slice_param->num_ref_idx_l0_active_minus1 > 30)
967            slice_param->num_ref_idx_l0_active_minus1 = 30;
968        for (i = slice_param->num_ref_idx_l0_active_minus1 + 1; i--;) {
969            object_surface_p surface = SURFACE(slice_param->RefPicList0[i].picture_id);
970            if (surface) {
971                uint32_t dpb_idx = GET_SURFACE_INFO_dpb_idx(surface->psb_surface);
972                if (dpb_idx < 16) {
973                    if (slice_param->RefPicList0[i].flags & VA_PICTURE_H264_BOTTOM_FIELD) {
974                        dpb_idx |= 0x10;
975                    }
976                    list0_inverse[dpb_idx] = i;
977                }
978            }
979        }
980        for (i = 0; i < 32; i += 4) {
981            reg_value = 0;
982            reg_value |= list0_inverse[i];
983            reg_value |= list0_inverse[i+1] << 8;
984            reg_value |= list0_inverse[i+2] << 16;
985            reg_value |= list0_inverse[i+3] << 24;
986            psb_cmdbuf_rendec_write(cmdbuf, reg_value);
987        }
988    }
989
990    if (slice_param->num_ref_idx_l1_active_minus1 > 28)
991        slice_param->num_ref_idx_l1_active_minus1 = 28;
992
993    /* Write Ref List 1 - but only need the valid ones */
994    for (i = 0; i <= slice_param->num_ref_idx_l1_active_minus1; i += 4) {
995        reg_value = 0;
996        reg_value |= PICTURE2INDEX(ctx, &slice_param->RefPicList1[i]);
997        reg_value |= PICTURE2INDEX(ctx, &slice_param->RefPicList1[i+1]) << 8;
998        reg_value |= PICTURE2INDEX(ctx, &slice_param->RefPicList1[i+2]) << 16;
999        reg_value |= PICTURE2INDEX(ctx, &slice_param->RefPicList1[i+3]) << 24;
1000        psb_cmdbuf_rendec_write(cmdbuf, reg_value);
1001    }
1002
1003    psb_cmdbuf_rendec_end(cmdbuf);
1004}
1005
1006static void psb__H264_build_register(context_H264_p ctx, VASliceParameterBufferH264 *slice_param)
1007{
1008    psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf;
1009    uint32_t reg_value;
1010
1011    psb_cmdbuf_reg_start_block(cmdbuf, 0);
1012
1013    reg_value = 0;
1014    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC, CR_VEC_ENTDEC_FE_CONTROL, ENTDEC_FE_PROFILE, ctx->profile);
1015    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC, CR_VEC_ENTDEC_FE_CONTROL, ENTDEC_FE_MODE, 1); /* 1 - H.264 */
1016
1017    psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_VEC, CR_VEC_ENTDEC_FE_CONTROL), reg_value);
1018
1019    /* write the FE registers */
1020    psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_VEC_H264, CR_VEC_H264_FE_SPS0),    ctx->reg_SPS0);
1021    psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_VEC_H264, CR_VEC_H264_FE_PPS0),    ctx->reg_PPS0);
1022    psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_VEC_H264, CR_VEC_H264_FE_CUR_PIC0),        ctx->reg_PIC0);
1023    psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_VEC_H264, CR_VEC_H264_FE_SLICE0),  ctx->slice0_params);
1024    psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_VEC_H264, CR_VEC_H264_FE_SLICE1),  ctx->slice1_params);
1025
1026    reg_value = 0;
1027    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_H264, CR_VEC_H264_FE_SLICE2, FIRST_MB_IN_SLICE, slice_param->first_mb_in_slice);
1028    psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_VEC_H264, CR_VEC_H264_FE_SLICE2), reg_value);
1029
1030    if (ctx->pic_params->num_slice_groups_minus1 >= 1) {
1031        ASSERT(ctx->slice_group_map_buffer);
1032        if (ctx->slice_group_map_buffer) {
1033            psb_cmdbuf_reg_set_address(cmdbuf, REGISTER_OFFSET(MSVDX_VEC_H264, CR_VEC_H264_FE_BASE_ADDR_SGM),
1034                                       ctx->slice_group_map_buffer, 0);
1035        }
1036    }
1037    psb_cmdbuf_reg_end_block(cmdbuf);
1038}
1039
1040/* Programme the Alt output if there is a rotation*/
1041static void psb__H264_setup_alternative_frame(context_H264_p ctx)
1042{
1043    uint32_t cmd;
1044    psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf;
1045    psb_surface_p target_surface = ctx->obj_context->current_render_target->psb_surface;
1046    psb_surface_p rotate_surface = ctx->obj_context->current_render_target->psb_surface_rotate;
1047    object_context_p obj_context = ctx->obj_context;
1048
1049    if (rotate_surface == NULL) {
1050        drv_debug_msg(VIDEO_DEBUG_GENERAL, "rotate surface is NULL, abort msvdx rotation\n");
1051        return;
1052    }
1053
1054    if (GET_SURFACE_INFO_rotate(rotate_surface) != obj_context->msvdx_rotate)
1055        drv_debug_msg(VIDEO_DEBUG_ERROR, "Display rotate mode does not match surface rotate mode!\n");
1056
1057
1058    /* CRendecBlock    RendecBlk( mCtrlAlloc , RENDEC_REGISTER_OFFSET(MSVDX_CMDS, VC1_LUMA_RANGE_MAPPING_BASE_ADDRESS) ); */
1059    psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_CMDS, VC1_LUMA_RANGE_MAPPING_BASE_ADDRESS));
1060
1061    psb_cmdbuf_rendec_write_address(cmdbuf, &rotate_surface->buf, rotate_surface->buf.buffer_ofs);
1062    psb_cmdbuf_rendec_write_address(cmdbuf, &rotate_surface->buf, rotate_surface->buf.buffer_ofs + rotate_surface->chroma_offset);
1063
1064    psb_cmdbuf_rendec_end(cmdbuf);
1065
1066    /* Set the rotation registers */
1067    psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION));
1068    cmd = 0;
1069    REGIO_WRITE_FIELD_LITE(cmd, MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION , ALT_PICTURE_ENABLE, 1);
1070    REGIO_WRITE_FIELD_LITE(cmd, MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION , ROTATION_ROW_STRIDE, rotate_surface->stride_mode);
1071    REGIO_WRITE_FIELD_LITE(cmd, MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION , RECON_WRITE_DISABLE, 0); /* FIXME Always generate Rec */
1072    REGIO_WRITE_FIELD_LITE(cmd, MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION , ROTATION_MODE, GET_SURFACE_INFO_rotate(rotate_surface));
1073    psb_cmdbuf_rendec_write(cmdbuf, cmd);
1074    *ctx->alt_output_flags = cmd;
1075
1076    cmd = 0;
1077    REGIO_WRITE_FIELD_LITE(cmd, MSVDX_CMDS, EXTENDED_ROW_STRIDE, EXT_ROW_STRIDE, target_surface->stride / 64);
1078    psb_cmdbuf_rendec_write(cmdbuf, cmd);
1079
1080    psb_cmdbuf_rendec_end(cmdbuf);
1081
1082    RELOC(*ctx->p_range_mapping_base0, rotate_surface->buf.buffer_ofs, &rotate_surface->buf);
1083    RELOC(*ctx->p_range_mapping_base1, rotate_surface->buf.buffer_ofs + rotate_surface->chroma_offset, &rotate_surface->buf);
1084}
1085
1086
1087static void psb__H264_build_rendec_params(context_H264_p ctx, VASliceParameterBufferH264 *slice_param)
1088{
1089    psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf;
1090    psb_surface_p target_surface = ctx->obj_context->current_render_target->psb_surface;
1091    VAPictureParameterBufferH264 *pic_params = ctx->pic_params;
1092    uint32_t reg_value;
1093    unsigned int i;
1094
1095    /* psb_cmdbuf_rendec_start_block( cmdbuf ); */
1096
1097    /* CHUNK: Entdec back-end profile and level */
1098    {
1099        psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_VEC, CR_VEC_ENTDEC_BE_CONTROL));
1100
1101        reg_value = 0;
1102        REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC, CR_VEC_ENTDEC_BE_CONTROL, ENTDEC_BE_PROFILE, ctx->profile);
1103        REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC, CR_VEC_ENTDEC_BE_CONTROL, ENTDEC_BE_MODE, 1); /* 1 - H.264 */
1104        psb_cmdbuf_rendec_write(cmdbuf, reg_value);
1105
1106        psb_cmdbuf_rendec_end(cmdbuf);
1107    }
1108
1109    /* CHUNK: SEQ Registers */
1110    /* send Slice Data for every slice */
1111    /* MUST be the last slice sent */
1112    psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_VEC, H264_CR_VEC_H264_BE_SPS0));
1113
1114    psb_cmdbuf_rendec_write(cmdbuf, ctx->reg_SPS0);
1115    psb_cmdbuf_rendec_write(cmdbuf, ctx->reg_PPS0);
1116    psb_cmdbuf_rendec_write(cmdbuf, ctx->reg_PIC0);
1117    psb_cmdbuf_rendec_write(cmdbuf, ctx->slice0_params);
1118    psb_cmdbuf_rendec_write(cmdbuf, ctx->slice1_params);
1119
1120    /* 5.5.75. VEC_H264_BE_BASE_ADDR_CUR_PIC */
1121    psb_buffer_p colocated_target_buffer = psb__H264_lookup_colocated_buffer(ctx, target_surface);
1122    ASSERT(colocated_target_buffer);
1123    if (colocated_target_buffer) {
1124        psb_cmdbuf_rendec_write_address(cmdbuf, colocated_target_buffer, colocated_target_buffer->buffer_ofs);
1125    } else {
1126        /* This is an error */
1127        psb_cmdbuf_rendec_write(cmdbuf, 0);
1128    }
1129
1130    reg_value = 0;
1131    REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_H264, CR_VEC_H264_BE_REF0, BE_LONGTERMFRAMEFLAG, ctx->long_term_frame_flags);
1132    psb_cmdbuf_rendec_write(cmdbuf, reg_value);
1133
1134    psb_cmdbuf_rendec_end(cmdbuf);
1135
1136    //#warning "TODO: MUST be done after fe slice1 (which gives MB address) "
1137    /*          REGIO_WRITE_REGISTER(0, MSVDX_VEC_H264, CR_VEC_H264_FE_BASE_ADDR_SGM, gui32SliceGroupType6BaseAddressHack); */
1138
1139    /* CHUNK: SCA */
1140    /* send Scaling Lists in High Profile for first slice*/
1141    if (ctx->profile == H264_HIGH_PROFILE) {
1142        psb__H264_build_SCA_chunk(ctx);
1143    }
1144
1145    /* CHUNK: POC */
1146    /* send Picture Order Counts (b frame only?) */
1147    /* maybe need a state variable to track if this has already been sent for the frame */
1148    if (slice_param->slice_type == ST_B) {
1149        psb__H264_build_picture_order_chunk(ctx);
1150    }
1151
1152    /* CHUNK: BIN */
1153    /* send B-slice information for B-slices */
1154    if (slice_param->slice_type == ST_B) {
1155        psb__H264_build_B_slice_chunk(ctx, slice_param);
1156    }
1157
1158    /* CHUNK: PIN */
1159    /* send P+B-slice information for P and B slices */
1160    if (slice_param->slice_type == ST_B ||  slice_param->slice_type == ST_P) {
1161        psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_VEC, H264_CR_VEC_H264_BE_LIST0));
1162
1163        if (slice_param->num_ref_idx_l0_active_minus1 > 31) {
1164            drv_debug_msg(VIDEO_DEBUG_ERROR, "num_ref_idx_l0_active_minus1(%d) is too big, limit it to 31.\n",
1165                               slice_param->num_ref_idx_l0_active_minus1);
1166            slice_param->num_ref_idx_l0_active_minus1 = 28;
1167        }
1168
1169        for (i = 0; i <= slice_param->num_ref_idx_l0_active_minus1; i += 4) {
1170            reg_value = 0;
1171            reg_value |= PICTURE2INDEX(ctx, &slice_param->RefPicList0[i]);
1172            reg_value |= PICTURE2INDEX(ctx, &slice_param->RefPicList0[i+1]) << 8;
1173            reg_value |= PICTURE2INDEX(ctx, &slice_param->RefPicList0[i+2]) << 16;
1174            reg_value |= PICTURE2INDEX(ctx, &slice_param->RefPicList0[i+3]) << 24;
1175            psb_cmdbuf_rendec_write(cmdbuf, reg_value);
1176        }
1177
1178        psb_cmdbuf_rendec_end(cmdbuf);
1179    }
1180
1181    /* CHUNK: DPB */
1182    /* send DPB information (for P and B slices?) only needed once per frame */
1183//      if ( sh->slice_type == ST_B || sh->slice_type == ST_P )
1184    if (pic_params->num_ref_frames > 0) {
1185        IMG_BOOL is_used[16];
1186        psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_CMDS, REFERENCE_PICTURE_BASE_ADDRESSES));
1187
1188        /* Mark all surfaces as unused */
1189        memset(is_used, 0, sizeof(is_used));
1190
1191        if (slice_param->num_ref_idx_l0_active_minus1 > 31)
1192            slice_param->num_ref_idx_l0_active_minus1 = 31;
1193        /* Mark onlys frame that are actualy used */
1194        for (i = 0; i <= slice_param->num_ref_idx_l0_active_minus1; i++) {
1195            object_surface_p ref_surface = SURFACE(slice_param->RefPicList0[i].picture_id);
1196            if (ref_surface) {
1197                uint32_t idx = GET_SURFACE_INFO_dpb_idx(ref_surface->psb_surface);
1198                if (idx < 16) {
1199                    is_used[idx] = IMG_TRUE;
1200                }
1201            }
1202        }
1203
1204        if (slice_param->num_ref_idx_l1_active_minus1 > 31)
1205            slice_param->num_ref_idx_l1_active_minus1 = 31;
1206
1207        /* Mark onlys frame that are actualy used */
1208        for (i = 0; i <= slice_param->num_ref_idx_l1_active_minus1; i++) {
1209            object_surface_p ref_surface = SURFACE(slice_param->RefPicList1[i].picture_id);
1210            if (ref_surface) {
1211                uint32_t idx = GET_SURFACE_INFO_dpb_idx(ref_surface->psb_surface);
1212                if (idx < 16) {
1213                    is_used[idx] = IMG_TRUE;
1214                }
1215            }
1216        }
1217
1218        if (pic_params->num_ref_frames > 16)
1219            pic_params->num_ref_frames = 16;
1220        /* Only load used surfaces */
1221        for (i = 0; i < pic_params->num_ref_frames; i++) {
1222            object_surface_p ref_surface = SURFACE(pic_params->ReferenceFrames[i].picture_id);
1223            psb_buffer_p buffer;
1224
1225            if (NULL == ref_surface) {
1226                drv_debug_msg(VIDEO_DEBUG_ERROR, "%s L%d Invalide reference surface handle\n",
1227                                   __FUNCTION__, __LINE__);
1228                return;
1229            }
1230
1231            buffer = ref_surface->psb_surface->ref_buf;
1232            /*
1233            drv_debug_msg(VIDEO_DEBUG_GENERAL, "pic_params->ReferenceFrames[%d] = %08x --> %08x frame_idx:0x%08x flags:%02x TopFieldOrderCnt: 0x%08x BottomFieldOrderCnt: 0x%08x %s\n",
1234                                     i,
1235                                     pic_params->ReferenceFrames[i].picture_id,
1236                                     ref_surface,
1237                                     pic_params->ReferenceFrames[i].frame_idx,
1238                                     pic_params->ReferenceFrames[i].flags,
1239                                     pic_params->ReferenceFrames[i].TopFieldOrderCnt,
1240                                     pic_params->ReferenceFrames[i].BottomFieldOrderCnt,
1241                                     is_used[i] ? "used" : "");
1242            */
1243            if (ref_surface && is_used[i] && buffer)
1244                // GET_SURFACE_INFO_is_used(ref_surface->psb_surface))
1245            {
1246                psb_cmdbuf_rendec_write_address(cmdbuf, buffer,
1247                                                buffer->buffer_ofs);
1248                psb_cmdbuf_rendec_write_address(cmdbuf, buffer,
1249                                                buffer->buffer_ofs +
1250                                                ref_surface->psb_surface->chroma_offset);
1251            } else {
1252                psb_cmdbuf_rendec_write(cmdbuf, 0xdeadbeef);
1253                psb_cmdbuf_rendec_write(cmdbuf, 0xdeadbeef);
1254            }
1255        }
1256        psb_cmdbuf_rendec_end(cmdbuf);
1257    }
1258
1259    /* CHUNK: MVA and MVB */
1260    /* works as long as weighted factors A and B commands remain the same */
1261    if ((pic_params->pic_fields.bits.weighted_pred_flag && (slice_param->slice_type == ST_P)) ||
1262        ((pic_params->pic_fields.bits.weighted_bipred_idc != 0) && (slice_param->slice_type == ST_B))) {
1263        IMG_UINT32 num_ref_0 = slice_param->num_ref_idx_l0_active_minus1;
1264
1265        psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_CMDS, H264_WEIGHTED_FACTORS_A));
1266
1267        if (num_ref_0 > 31)
1268            num_ref_0 = 31;
1269
1270        /* weighted factors */
1271        for (i = 0; i <= num_ref_0; i++) {
1272            reg_value = 0;
1273            REGIO_WRITE_FIELD_MASKEDLITE(reg_value, MSVDX_CMDS, H264_WEIGHTED_FACTORS_A, CR_WEIGHT_A,   slice_param->chroma_weight_l0[i][1]);/* Cr - 1 */
1274            REGIO_WRITE_FIELD_MASKEDLITE(reg_value, MSVDX_CMDS, H264_WEIGHTED_FACTORS_A, CB_WEIGHT_A,   slice_param->chroma_weight_l0[i][0]);/* Cb - 0 */
1275            REGIO_WRITE_FIELD_MASKEDLITE(reg_value, MSVDX_CMDS, H264_WEIGHTED_FACTORS_A, Y_WEIGHT_A,    slice_param->luma_weight_l0[i]);
1276
1277            psb_cmdbuf_rendec_write(cmdbuf, reg_value);
1278        }
1279        /* pad remainder */
1280        for (; i < 32; i++) {
1281            psb_cmdbuf_rendec_write(cmdbuf, 0);
1282        }
1283
1284        /* weighted offsets */
1285        for (i = 0; i <= num_ref_0; i++) {
1286            reg_value = 0;
1287            REGIO_WRITE_FIELD_MASKEDLITE(reg_value, MSVDX_CMDS, H264_WEIGHTED_OFFSET_A, CR_OFFSET_A,    slice_param->chroma_offset_l0[i][1]);/* Cr - 1 */
1288            REGIO_WRITE_FIELD_MASKEDLITE(reg_value, MSVDX_CMDS, H264_WEIGHTED_OFFSET_A, CB_OFFSET_A,    slice_param->chroma_offset_l0[i][0]);/* Cb - 0 */
1289            REGIO_WRITE_FIELD_MASKEDLITE(reg_value, MSVDX_CMDS, H264_WEIGHTED_OFFSET_A, Y_OFFSET_A,     slice_param->luma_offset_l0[i]);
1290
1291            psb_cmdbuf_rendec_write(cmdbuf, reg_value);
1292        }
1293        /* pad remainder */
1294        for (; i < 32; i++) {
1295            psb_cmdbuf_rendec_write(cmdbuf, 0);
1296        }
1297        psb_cmdbuf_rendec_end(cmdbuf);
1298
1299        if (slice_param->slice_type == ST_B) {
1300            IMG_UINT32 num_ref_1 = slice_param->num_ref_idx_l1_active_minus1;
1301
1302            psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_CMDS, H264_WEIGHTED_FACTORS_B));
1303
1304            if (num_ref_1 > 31) {
1305                drv_debug_msg(VIDEO_DEBUG_ERROR, "num_ref_1 shouldn't be larger than 31\n");
1306                num_ref_1 = 31;
1307            }
1308
1309            /* weighted factors */
1310            for (i = 0; i <= num_ref_1; i++) {
1311                reg_value = 0;
1312                REGIO_WRITE_FIELD_MASKEDLITE(reg_value, MSVDX_CMDS, H264_WEIGHTED_FACTORS_B, CR_WEIGHT_B,       slice_param->chroma_weight_l1[i][1]);/* Cr - 1 */
1313                REGIO_WRITE_FIELD_MASKEDLITE(reg_value, MSVDX_CMDS, H264_WEIGHTED_FACTORS_B, CB_WEIGHT_B,       slice_param->chroma_weight_l1[i][0]);/* Cb - 0 */
1314                REGIO_WRITE_FIELD_MASKEDLITE(reg_value, MSVDX_CMDS, H264_WEIGHTED_FACTORS_B, Y_WEIGHT_B,        slice_param->luma_weight_l1[i]);
1315
1316                psb_cmdbuf_rendec_write(cmdbuf, reg_value);
1317            }
1318            /* pad remainder */
1319            for (; i < 32; i++) {
1320                psb_cmdbuf_rendec_write(cmdbuf, 0);
1321            }
1322
1323            /* weighted offsets */
1324            for (i = 0; i <= num_ref_1; i++) {
1325                reg_value = 0;
1326                REGIO_WRITE_FIELD_MASKEDLITE(reg_value, MSVDX_CMDS, H264_WEIGHTED_OFFSET_B, CR_OFFSET_B,        slice_param->chroma_offset_l1[i][1]);/* Cr - 1 */
1327                REGIO_WRITE_FIELD_MASKEDLITE(reg_value, MSVDX_CMDS, H264_WEIGHTED_OFFSET_B, CB_OFFSET_B,        slice_param->chroma_offset_l1[i][0]);/* Cb - 0 */
1328                REGIO_WRITE_FIELD_MASKEDLITE(reg_value, MSVDX_CMDS, H264_WEIGHTED_OFFSET_B, Y_OFFSET_B, slice_param->luma_offset_l1[i]);
1329
1330                psb_cmdbuf_rendec_write(cmdbuf, reg_value);
1331            }
1332            /* pad remainder */
1333            for (; i < 32; i++) {
1334                psb_cmdbuf_rendec_write(cmdbuf, 0);
1335            }
1336            psb_cmdbuf_rendec_end(cmdbuf);
1337        }
1338    }
1339
1340
1341    /* CHUNK: SEQ Commands 1 */
1342    /* send Slice Data for every slice */
1343    /* MUST be the last slice sent */
1344    psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_CMDS, DISPLAY_PICTURE_SIZE));
1345
1346    reg_value = 0;
1347    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, DISPLAY_PICTURE_SIZE, DISPLAY_PICTURE_HEIGHT, (ctx->picture_height_mb * 16) - 1);
1348    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, DISPLAY_PICTURE_SIZE, DISPLAY_PICTURE_WIDTH, (ctx->picture_width_mb * 16) - 1);
1349    psb_cmdbuf_rendec_write(cmdbuf, reg_value);
1350
1351    reg_value = 0;
1352    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, CODED_PICTURE_SIZE, CODED_PICTURE_HEIGHT, (ctx->picture_height_mb * 16) - 1);
1353    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, CODED_PICTURE_SIZE, CODED_PICTURE_WIDTH, (ctx->picture_width_mb * 16) - 1);
1354    psb_cmdbuf_rendec_write(cmdbuf, reg_value);
1355
1356    reg_value = 0;
1357    // TODO: Must check how these should be set
1358    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, OPERATING_MODE, CHROMA_INTERLEAVED, 0);
1359    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, OPERATING_MODE, ROW_STRIDE, target_surface->stride_mode);
1360    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, OPERATING_MODE, CODEC_PROFILE, ctx->profile);
1361    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, OPERATING_MODE, CODEC_MODE, 1);       /* H.264 */
1362    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, OPERATING_MODE, ASYNC_MODE, (ctx->two_pass_mode && !ctx->pic_params->seq_fields.bits.mb_adaptive_frame_field_flag));
1363    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, OPERATING_MODE, CHROMA_FORMAT, pic_params->seq_fields.bits.chroma_format_idc);
1364    psb_cmdbuf_rendec_write(cmdbuf, reg_value);
1365
1366    ctx->obj_context->operating_mode = reg_value;
1367
1368    if ((ctx->deblock_mode ==  DEBLOCK_INTRA_OOLD) && ctx->two_pass_mode) { /* Need to mark which buf is to be used as ref*/
1369        /* LUMA_RECONSTRUCTED_PICTURE_BASE_ADDRESSES */
1370        psb_cmdbuf_rendec_write_address(cmdbuf, target_surface->in_loop_buf, target_surface->in_loop_buf->buffer_ofs);
1371
1372        /* CHROMA_RECONSTRUCTED_PICTURE_BASE_ADDRESSES */
1373        psb_cmdbuf_rendec_write_address(cmdbuf, target_surface->in_loop_buf, target_surface->in_loop_buf->buffer_ofs + target_surface->chroma_offset);
1374        target_surface->ref_buf = target_surface->in_loop_buf;
1375    } else {
1376        psb_cmdbuf_rendec_write_address(cmdbuf, &target_surface->buf, target_surface->buf.buffer_ofs);
1377        psb_cmdbuf_rendec_write_address(cmdbuf, &target_surface->buf, target_surface->buf.buffer_ofs + target_surface->chroma_offset);
1378        target_surface->ref_buf = &target_surface->buf;
1379    }
1380    /* Aux Msb Buffer base address: H.264 does not use this command */
1381    reg_value = 0;
1382    psb_cmdbuf_rendec_write(cmdbuf, reg_value);
1383
1384    /* Intra Reference Cache */
1385    psb_cmdbuf_rendec_write_address(cmdbuf, &ctx->reference_cache, 0);
1386
1387    reg_value = 0;
1388    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, MC_CACHE_CONFIGURATION, CONFIG_REF_OFFSET, CACHE_REF_OFFSET);
1389    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, MC_CACHE_CONFIGURATION, CONFIG_ROW_OFFSET, CACHE_ROW_OFFSET);
1390    psb_cmdbuf_rendec_write(cmdbuf, reg_value);
1391
1392    /* Vc1 Intensity compensation: H.264 does not use this command */
1393    reg_value = 0;
1394    psb_cmdbuf_rendec_write(cmdbuf, reg_value);
1395
1396    reg_value = 0;
1397    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, H264_WEIGHTED_FACTOR_DENOMINATOR, C_LOG2_WEIGHT_DENOM, slice_param->chroma_log2_weight_denom);
1398    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, H264_WEIGHTED_FACTOR_DENOMINATOR, Y_LOG2_WEIGHT_DENOM, slice_param->luma_log2_weight_denom);
1399    psb_cmdbuf_rendec_write(cmdbuf, reg_value);
1400
1401    psb_cmdbuf_rendec_end(cmdbuf);
1402
1403    /* CHUNK: SEQ Commands 2 */
1404    /* send Slice Data for every slice */
1405    /* MUST be the last slice sent */
1406    {
1407        IMG_UINT32 ui32Mode  = pic_params->pic_fields.bits.weighted_pred_flag | (pic_params->pic_fields.bits.weighted_bipred_idc << 1);
1408
1409        psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_CMDS, SLICE_PARAMS));
1410
1411        reg_value = 0;
1412        REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, SLICE_PARAMS, CONSTRAINED_INTRA_PRED, pic_params->pic_fields.bits.constrained_intra_pred_flag);
1413        REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, SLICE_PARAMS, MODE_CONFIG, ui32Mode);
1414        REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, SLICE_PARAMS, DISABLE_DEBLOCK_FILTER_IDC, slice_param->disable_deblocking_filter_idc);
1415        REGIO_WRITE_FIELD_MASKEDLITE(reg_value, MSVDX_CMDS, SLICE_PARAMS, SLICE_ALPHA_CO_OFFSET_DIV2, slice_param->slice_alpha_c0_offset_div2);
1416        REGIO_WRITE_FIELD_MASKEDLITE(reg_value, MSVDX_CMDS, SLICE_PARAMS, SLICE_BETA_OFFSET_DIV2, slice_param->slice_beta_offset_div2);
1417        REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, SLICE_PARAMS, SLICE_FIELD_TYPE, ctx->field_type);
1418        REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, SLICE_PARAMS, SLICE_CODE_TYPE, aSliceTypeVAtoMsvdx[slice_param->slice_type % 5]);
1419        psb_cmdbuf_rendec_write(cmdbuf, reg_value);
1420
1421        /* Store slice parameters in header */
1422        *(ctx->p_slice_params) = reg_value;
1423
1424        psb_cmdbuf_rendec_end(cmdbuf);
1425    }
1426
1427    /*          If this a two pass mode deblock, then we will perform the rotation as part of the
1428     *          2nd pass deblock procedure
1429     */
1430    if (!ctx->two_pass_mode && CONTEXT_ROTATE(ctx->obj_context)) {/* FIXME field coded should not issue */
1431        drv_debug_msg(VIDEO_DEBUG_GENERAL, "Setup rotate surface (%d) into command stream\n",
1432                                 ctx->obj_context->msvdx_rotate);
1433
1434        psb__H264_setup_alternative_frame(ctx);
1435    }
1436
1437
1438    /* psb_cmdbuf_rendec_end_block( cmdbuf ); */
1439}
1440
1441/*
1442 * Adds a VASliceParameterBuffer to the list of slice params
1443 */
1444static VAStatus psb__H264_add_slice_param(context_H264_p ctx, object_buffer_p obj_buffer)
1445{
1446    ASSERT(obj_buffer->type == VASliceParameterBufferType);
1447    if (ctx->slice_param_list_idx >= ctx->slice_param_list_size) {
1448        unsigned char *new_list;
1449        ctx->slice_param_list_size += 8;
1450        new_list = realloc(ctx->slice_param_list,
1451                           sizeof(object_buffer_p) * ctx->slice_param_list_size);
1452        if (NULL == new_list) {
1453            return VA_STATUS_ERROR_ALLOCATION_FAILED;
1454        }
1455        ctx->slice_param_list = (object_buffer_p*) new_list;
1456    }
1457    ctx->slice_param_list[ctx->slice_param_list_idx] = obj_buffer;
1458    ctx->slice_param_list_idx++;
1459    return VA_STATUS_SUCCESS;
1460}
1461
1462static void psb__H264_write_kick(context_H264_p ctx, VASliceParameterBufferH264 *slice_param)
1463{
1464    psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf;
1465
1466    (void) slice_param; /* Unused for now */
1467
1468    *cmdbuf->cmd_idx++ = CMD_COMPLETION;
1469}
1470
1471#ifndef DE3_FIRMWARE
1472static void psb__H264_FE_state(context_H264_p ctx)
1473{
1474    uint32_t lldma_record_offset;
1475    psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf;
1476
1477    *cmdbuf->cmd_idx++ = CMD_HEADER_VC1;
1478    ctx->p_slice_params = cmdbuf->cmd_idx;
1479    *cmdbuf->cmd_idx++ = 0;
1480
1481
1482    lldma_record_offset = psb_cmdbuf_lldma_create(cmdbuf, &(ctx->preload_buffer), 0,
1483                          sizeof(PRELOAD), 0, LLDMA_TYPE_H264_PRELOAD_SAVE);
1484    RELOC(*cmdbuf->cmd_idx, lldma_record_offset, &(cmdbuf->buf));
1485    cmdbuf->cmd_idx++;
1486
1487    lldma_record_offset = psb_cmdbuf_lldma_create(cmdbuf, &(ctx->preload_buffer), 0,
1488                          sizeof(PRELOAD), 0, LLDMA_TYPE_H264_PRELOAD_RESTORE);
1489    RELOC(*cmdbuf->cmd_idx, lldma_record_offset, &(cmdbuf->buf));
1490    cmdbuf->cmd_idx++;
1491
1492    ctx->slice_first_pic_last = cmdbuf->cmd_idx++;
1493
1494    ctx->p_range_mapping_base0 = cmdbuf->cmd_idx++;
1495    ctx->p_range_mapping_base1 = cmdbuf->cmd_idx++;
1496
1497    ctx->alt_output_flags = cmdbuf->cmd_idx++;
1498    *ctx->alt_output_flags = 0;
1499}
1500#else
1501static void psb__H264_FE_state(context_H264_p ctx)
1502{
1503    psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf;
1504    CTRL_ALLOC_HEADER *cmd_header = (CTRL_ALLOC_HEADER *)psb_cmdbuf_alloc_space(cmdbuf, sizeof(CTRL_ALLOC_HEADER));
1505
1506    memset(cmd_header, 0, sizeof(CTRL_ALLOC_HEADER));
1507    cmd_header->ui32Cmd_AdditionalParams = CMD_CTRL_ALLOC_HEADER;
1508    RELOC(cmd_header->ui32ExternStateBuffAddr, 0, &ctx->preload_buffer);
1509    cmd_header->ui32MacroblockParamAddr = 0; /* Only EC needs to set this */
1510
1511    ctx->p_slice_params = &cmd_header->ui32SliceParams;
1512    cmd_header->ui32SliceParams = 0;
1513
1514    ctx->slice_first_pic_last = &cmd_header->uiSliceFirstMbYX_uiPicLastMbYX;
1515
1516    ctx->p_range_mapping_base0 = &cmd_header->ui32AltOutputAddr[0];
1517    ctx->p_range_mapping_base1 = &cmd_header->ui32AltOutputAddr[1];
1518
1519    ctx->alt_output_flags = &cmd_header->ui32AltOutputFlags;
1520    cmd_header->ui32AltOutputFlags = 0;
1521}
1522#endif
1523
1524static void psb__H264_preprocess_slice(context_H264_p ctx,
1525                                       VASliceParameterBufferH264 *slice_param)
1526{
1527    VAPictureParameterBufferH264 *pic_params = ctx->pic_params;
1528    uint32_t slice_qpy;
1529
1530    ctx->first_mb_x = slice_param->first_mb_in_slice % ctx->picture_width_mb;
1531    ctx->first_mb_y = slice_param->first_mb_in_slice / ctx->picture_width_mb;
1532    ctx->slice0_params = 0;
1533    ctx->slice1_params = 0;
1534
1535    ASSERT(pic_params);
1536    if (!pic_params) {
1537        /* This is an error */
1538        return;
1539    }
1540
1541    if (!pic_params->pic_fields.bits.field_pic_flag && pic_params->seq_fields.bits.mb_adaptive_frame_field_flag) {
1542        /* If in MBAFF mode multiply MB y-address by 2 */
1543        ctx->first_mb_y *= 2;
1544    }
1545
1546    slice_qpy = 26 + pic_params->pic_init_qp_minus26 + slice_param->slice_qp_delta;     /* (7-27) */
1547
1548    REGIO_WRITE_FIELD_LITE(ctx->slice0_params, MSVDX_VEC_H264, CR_VEC_H264_BE_SLICE0, BE_DIRECT_SPATIAL_MV_PRED_FLAG,                   slice_param->direct_spatial_mv_pred_flag);
1549    REGIO_WRITE_FIELD_LITE(ctx->slice0_params, MSVDX_VEC_H264, CR_VEC_H264_BE_SLICE0, H264_BE_SLICE0_DISABLE_DEBLOCK_FILTER_IDC,        slice_param->disable_deblocking_filter_idc);
1550    REGIO_WRITE_FIELD_MASKEDLITE(ctx->slice0_params, MSVDX_VEC_H264, CR_VEC_H264_BE_SLICE0, H264_BE_SLICE0_ALPHA_CO_OFFSET_DIV2,        slice_param->slice_alpha_c0_offset_div2);
1551    REGIO_WRITE_FIELD_MASKEDLITE(ctx->slice0_params, MSVDX_VEC_H264, CR_VEC_H264_BE_SLICE0, H264_BE_SLICE0_BETA_OFFSET_DIV2,            slice_param->slice_beta_offset_div2);
1552    REGIO_WRITE_FIELD_LITE(ctx->slice0_params, MSVDX_VEC_H264, CR_VEC_H264_BE_SLICE0, H264_BE_SLICE0_FIELD_TYPE,                        ctx->field_type);
1553    REGIO_WRITE_FIELD_LITE(ctx->slice0_params, MSVDX_VEC_H264, CR_VEC_H264_FE_SLICE0, SLICETYPE,                                        aSliceTypeVAtoMsvdx[ slice_param->slice_type % 5]);
1554    REGIO_WRITE_FIELD_LITE(ctx->slice0_params, MSVDX_VEC_H264, CR_VEC_H264_FE_SLICE0, CABAC_INIT_IDC,                                   slice_param->cabac_init_idc);
1555    REGIO_WRITE_FIELD_LITE(ctx->slice0_params, MSVDX_VEC_H264, CR_VEC_H264_FE_SLICE0, SLICECOUNT,                                       ctx->slice_count);
1556
1557    REGIO_WRITE_FIELD_LITE(ctx->slice1_params, MSVDX_VEC_H264, CR_VEC_H264_FE_SLICE1, FIRST_MB_IN_SLICE_X,      ctx->first_mb_x);
1558    REGIO_WRITE_FIELD_LITE(ctx->slice1_params, MSVDX_VEC_H264, CR_VEC_H264_FE_SLICE1, FIRST_MB_IN_SLICE_Y,      ctx->first_mb_y);
1559    REGIO_WRITE_FIELD_LITE(ctx->slice1_params, MSVDX_VEC_H264, CR_VEC_H264_FE_SLICE1, SLICEQPY,                 slice_qpy);
1560    REGIO_WRITE_FIELD_LITE(ctx->slice1_params, MSVDX_VEC_H264, CR_VEC_H264_FE_SLICE1, NUM_REF_IDX_L0_ACTIVE_MINUS1, slice_param->num_ref_idx_l0_active_minus1);
1561    REGIO_WRITE_FIELD_LITE(ctx->slice1_params, MSVDX_VEC_H264, CR_VEC_H264_FE_SLICE1, NUM_REF_IDX_L1_ACTIVE_MINUS1, slice_param->num_ref_idx_l1_active_minus1);
1562
1563    IMG_BOOL deblocker_disable = (slice_param->disable_deblocking_filter_idc  == 1);
1564
1565    if (deblocker_disable) {
1566        if (ctx->obj_context->is_oold) {
1567            ctx->deblock_mode = DEBLOCK_INTRA_OOLD;
1568            ctx->two_pass_mode = 1;
1569            REGIO_WRITE_FIELD_LITE(ctx->reg_SPS0, MSVDX_VEC_H264, CR_VEC_H264_BE_SPS0, H264_BE_SPS0_2PASS_FLAG, ctx->two_pass_mode);
1570        } else
1571            ctx->deblock_mode = DEBLOCK_STD;
1572    } else {
1573        ctx->deblock_mode = DEBLOCK_STD;
1574    }
1575}
1576
1577/* **************************************************************************************************************** */
1578/* Prepacked calculates VLC table offsets and reg address                                                           */
1579/* **************************************************************************************************************** */
1580static const  IMG_UINT32 ui32H264VLCTableRegValPair[] = {
1581    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x00000000), 0x00026000,
1582    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x00000004), 0x000738a0,
1583    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x00000008), 0x000828f4,
1584    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x0000000c), 0x000a312d,
1585    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x00000010), 0x000b5959,
1586    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x00000014), 0x000c517b,
1587    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x00000018), 0x000d1196,
1588    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x0000001c), 0x000db1ad,
1589    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x00000020), 0x000e21be,
1590    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x00000024), 0x000e59c8,
1591    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x00000028), 0x000e79cd,
1592    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x0000002c), 0x000eb1d3,
1593    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x00000030), 0x000ed1d8,
1594    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x00000034), 0x000f09dd,
1595    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x00000038), 0x000f71e7,
1596    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x0000003c), 0x000001f6,
1597    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x00000040), 0x1256a4dd,
1598    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x00000044), 0x01489292,
1599    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x00000048), 0x11248050,
1600    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x0000004c), 0x00000002,
1601    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x00000050), 0x00002a02,
1602    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x00000054), 0x0108282a,
1603};
1604
1605
1606static void psb__H264_write_VLC_tables(context_H264_p ctx)
1607{
1608    psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf;
1609    unsigned int i;
1610
1611    psb_cmdbuf_skip_start_block(cmdbuf, SKIP_ON_CONTEXT_SWITCH);
1612
1613    /* VLC Table */
1614    /* Write a LLDMA Cmd to transfer VLD Table data */
1615#ifndef DE3_FIRMWARE
1616    psb_cmdbuf_lldma_write_cmdbuf(cmdbuf, &ctx->vlc_packed_table, 0,
1617                                  sizeof(ui16H264VLCTableData),
1618                                  0, LLDMA_TYPE_VLC_TABLE);
1619#else
1620    psb_cmdbuf_dma_write_cmdbuf(cmdbuf, &ctx->vlc_packed_table, 0,
1621                                  sizeof(ui16H264VLCTableData), 0,
1622                                  DMA_TYPE_VLC_TABLE);
1623#endif
1624
1625    /* Writes the VLD offsets.  mtx need only do this on context switch*/
1626    psb_cmdbuf_reg_start_block(cmdbuf, 0);
1627
1628    for (i = 0; i < (sizeof(ui32H264VLCTableRegValPair) / sizeof(ui32H264VLCTableRegValPair[0])) ; i += 2) {
1629        psb_cmdbuf_reg_set(cmdbuf, ui32H264VLCTableRegValPair[i] , ui32H264VLCTableRegValPair[i + 1]);
1630    }
1631
1632    psb_cmdbuf_reg_end_block(cmdbuf);
1633
1634    psb_cmdbuf_skip_end_block(cmdbuf);
1635}
1636
1637static VAStatus psb__H264_process_slice(context_H264_p ctx,
1638                                        VASliceParameterBufferH264 *slice_param,
1639                                        object_buffer_p obj_buffer)
1640{
1641    VAStatus vaStatus = VA_STATUS_SUCCESS;
1642
1643    ASSERT((obj_buffer->type == VASliceDataBufferType) || (obj_buffer->type == VAProtectedSliceDataBufferType));
1644
1645#if 0
1646    drv_debug_msg(VIDEO_DEBUG_GENERAL, "H264 process slice %d\n", ctx->slice_count);
1647    drv_debug_msg(VIDEO_DEBUG_GENERAL, "    profile = %s\n", profile2str[ctx->profile]);
1648    drv_debug_msg(VIDEO_DEBUG_GENERAL, "    size = %08x offset = %08x\n", slice_param->slice_data_size, slice_param->slice_data_offset);
1649    drv_debug_msg(VIDEO_DEBUG_GENERAL, "    first mb = %d macroblock offset = %d\n", slice_param->first_mb_in_slice, slice_param->slice_data_bit_offset);
1650    drv_debug_msg(VIDEO_DEBUG_GENERAL, "    slice_data_flag = %d\n", slice_param->slice_data_flag);
1651    drv_debug_msg(VIDEO_DEBUG_GENERAL, "    coded size = %dx%d\n", ctx->picture_width_mb, ctx->picture_height_mb);
1652    drv_debug_msg(VIDEO_DEBUG_GENERAL, "    slice type = %s\n", slice2str[(slice_param->slice_type % 5)]);
1653    drv_debug_msg(VIDEO_DEBUG_GENERAL, "    weighted_pred_flag = %d weighted_bipred_idc = %d\n", ctx->pic_params->pic_fields.bits.weighted_pred_flag, ctx->pic_params->pic_fields.bits.weighted_bipred_idc);
1654#endif
1655
1656    if ((slice_param->slice_data_flag == VA_SLICE_DATA_FLAG_BEGIN) ||
1657        (slice_param->slice_data_flag == VA_SLICE_DATA_FLAG_ALL)) {
1658        if (0 == slice_param->slice_data_size) {
1659            vaStatus = VA_STATUS_ERROR_UNKNOWN;
1660            DEBUG_FAILURE;
1661            return vaStatus;
1662        }
1663        ASSERT(!ctx->split_buffer_pending);
1664
1665        psb__H264_preprocess_slice(ctx, slice_param);
1666
1667        /* Initialise the command buffer */
1668        /* TODO: Reuse current command buffer until full */
1669        psb_context_get_next_cmdbuf(ctx->obj_context);
1670
1671        psb__H264_FE_state(ctx);
1672
1673        psb__H264_write_VLC_tables(ctx);
1674
1675#ifndef DE3_FIRMWARE
1676        psb_cmdbuf_lldma_write_bitstream(ctx->obj_context->cmdbuf,
1677                                         obj_buffer->psb_buffer,
1678                                         obj_buffer->psb_buffer->buffer_ofs + slice_param->slice_data_offset,
1679                                         slice_param->slice_data_size,
1680                                         slice_param->slice_data_bit_offset,
1681                                         CMD_ENABLE_RBDU_EXTRACTION);
1682#else
1683
1684        psb_cmdbuf_dma_write_bitstream(ctx->obj_context->cmdbuf,
1685                                         obj_buffer->psb_buffer,
1686                                         obj_buffer->psb_buffer->buffer_ofs + slice_param->slice_data_offset,
1687                                         slice_param->slice_data_size,
1688                                         slice_param->slice_data_bit_offset,
1689                                         CMD_ENABLE_RBDU_EXTRACTION /*| CMD_SR_VERIFY_STARTCODE*/);
1690                                         /* CMD_SR_VERIFY_STARTCODE, clean this flag to work when no start code in slice data */
1691#endif
1692
1693        if (slice_param->slice_data_flag == VA_SLICE_DATA_FLAG_BEGIN) {
1694            ctx->split_buffer_pending = TRUE;
1695        }
1696    } else {
1697        ASSERT(ctx->split_buffer_pending);
1698        ASSERT(0 == slice_param->slice_data_offset);
1699        /* Create LLDMA chain to continue buffer */
1700        if (slice_param->slice_data_size) {
1701#ifndef DE3_FIRMWARE
1702            psb_cmdbuf_lldma_write_bitstream_chained(ctx->obj_context->cmdbuf,
1703                    obj_buffer->psb_buffer,
1704                    slice_param->slice_data_size);
1705#else
1706            psb_cmdbuf_dma_write_bitstream_chained(ctx->obj_context->cmdbuf,
1707                    obj_buffer->psb_buffer,
1708                    slice_param->slice_data_size);
1709#endif
1710        }
1711    }
1712
1713    if ((slice_param->slice_data_flag == VA_SLICE_DATA_FLAG_ALL) ||
1714        (slice_param->slice_data_flag == VA_SLICE_DATA_FLAG_END)) {
1715        if (slice_param->slice_data_flag == VA_SLICE_DATA_FLAG_END) {
1716            ASSERT(ctx->split_buffer_pending);
1717        }
1718
1719        psb__H264_build_register(ctx, slice_param);
1720
1721        psb__H264_build_rendec_params(ctx, slice_param);
1722
1723        psb__H264_write_kick(ctx, slice_param);
1724
1725        ctx->split_buffer_pending = FALSE;
1726        ctx->obj_context->video_op = psb_video_vld;
1727        ctx->obj_context->flags = 0;
1728        if (ctx->slice_count == 0) {
1729            ctx->obj_context->flags |= FW_VA_RENDER_IS_FIRST_SLICE;
1730        }
1731        if (ctx->pic_params->seq_fields.bits.mb_adaptive_frame_field_flag) {
1732            ctx->obj_context->flags |= FW_VA_RENDER_IS_H264_MBAFF;
1733        }
1734        if (ctx->two_pass_mode) {
1735            ctx->obj_context->flags |= FW_VA_RENDER_IS_TWO_PASS_DEBLOCK;
1736        }
1737        ctx->obj_context->flags |= FW_VA_RENDER_IS_VLD_NOT_MC; /* FW_ERROR_DETECTION_AND_RECOVERY */
1738
1739#ifdef PSBVIDEO_MSVDX_EC
1740	if (ctx->obj_context->driver_data->ec_enabled)
1741            ctx->obj_context->flags |= (FW_ERROR_DETECTION_AND_RECOVERY); /* FW_ERROR_DETECTION_AND_RECOVERY */
1742#endif
1743
1744        ctx->obj_context->first_mb = (ctx->first_mb_y << 8) | ctx->first_mb_x;
1745        ctx->obj_context->last_mb = (((ctx->picture_height_mb >> ctx->pic_params->pic_fields.bits.field_pic_flag) - 1) << 8) | (ctx->picture_width_mb - 1);
1746        *ctx->slice_first_pic_last = (ctx->obj_context->first_mb << 16) | (ctx->obj_context->last_mb);
1747
1748        if (psb_context_submit_cmdbuf(ctx->obj_context)) {
1749            vaStatus = VA_STATUS_ERROR_UNKNOWN;
1750        }
1751
1752        ctx->slice_count++;
1753        ctx->slice_param = slice_param;
1754    }
1755    return vaStatus;
1756}
1757
1758static VAStatus psb__H264_process_slice_data(context_H264_p ctx, object_buffer_p obj_buffer)
1759{
1760    VAStatus vaStatus = VA_STATUS_SUCCESS;
1761    VASliceParameterBufferH264 *slice_param;
1762    int buffer_idx = 0;
1763    unsigned int element_idx = 0;
1764
1765    ASSERT((obj_buffer->type == VASliceDataBufferType) || (obj_buffer->type == VAProtectedSliceDataBufferType));
1766
1767    ASSERT(ctx->pic_params);
1768    ASSERT(ctx->slice_param_list_idx);
1769
1770    if (!ctx->pic_params) {
1771        /* Picture params missing */
1772        return VA_STATUS_ERROR_UNKNOWN;
1773    }
1774    if ((NULL == obj_buffer->psb_buffer) ||
1775        (0 == obj_buffer->size)) {
1776        /* We need to have data in the bitstream buffer */
1777        return VA_STATUS_ERROR_UNKNOWN;
1778    }
1779
1780    while (buffer_idx < ctx->slice_param_list_idx) {
1781        object_buffer_p slice_buf = ctx->slice_param_list[buffer_idx];
1782        if (element_idx >= slice_buf->num_elements) {
1783            /* Move to next buffer */
1784            element_idx = 0;
1785            buffer_idx++;
1786            continue;
1787        }
1788
1789        slice_param = (VASliceParameterBufferH264 *) slice_buf->buffer_data;
1790        slice_param += element_idx;
1791        element_idx++;
1792        vaStatus = psb__H264_process_slice(ctx, slice_param, obj_buffer);
1793        if (vaStatus != VA_STATUS_SUCCESS) {
1794            DEBUG_FAILURE;
1795            break;
1796        }
1797    }
1798    ctx->slice_param_list_idx = 0;
1799
1800    return vaStatus;
1801}
1802
1803#ifdef PSBVIDEO_MSVDX_EC
1804static void psb__H264_choose_ec_frames(context_H264_p ctx)
1805{
1806    /* If reference picture list has a valid entry, this is a P or B frame and we conceal from the frame that is at the top of the list*/
1807    if (ctx->slice_param->num_ref_idx_l0_active_minus1 >= 0)
1808    {
1809        object_surface_p ref_surface = SURFACE(ctx->slice_param->RefPicList0[0].picture_id);
1810        ctx->obj_context->ec_target = ref_surface;
1811    }
1812    /* Otherwise we conceal from the previous I or P frame*/
1813    if (!ctx->obj_context->ec_target)
1814    {
1815        ctx->obj_context->ec_target = ctx->obj_context->ec_candidate;
1816    }
1817
1818    if (ctx->slice_param->slice_type != ST_B)
1819    {
1820        ctx->obj_context->ec_candidate = ctx->obj_context->current_render_target; /* in case the next frame is an I frame we will need this */
1821    }
1822    if (!ctx->obj_context->ec_target) {
1823        ctx->obj_context->ec_target = ctx->obj_context->current_render_target;
1824    }
1825}
1826#endif
1827
1828static VAStatus pnw_H264_BeginPicture(
1829    object_context_p obj_context)
1830{
1831    INIT_CONTEXT_H264
1832
1833    if (ctx->pic_params) {
1834        free(ctx->pic_params);
1835        ctx->pic_params = NULL;
1836    }
1837    if (ctx->iq_matrix) {
1838        free(ctx->iq_matrix);
1839        ctx->iq_matrix = NULL;
1840    }
1841    ctx->slice_count = 0;
1842    ctx->slice_group_map_buffer = NULL;
1843    ctx->deblock_mode = DEBLOCK_NONE;
1844
1845    return VA_STATUS_SUCCESS;
1846}
1847
1848static VAStatus pnw_H264_RenderPicture(
1849    object_context_p obj_context,
1850    object_buffer_p *buffers,
1851    int num_buffers)
1852{
1853    int i;
1854    INIT_CONTEXT_H264
1855    VAStatus vaStatus = VA_STATUS_SUCCESS;
1856
1857    for (i = 0; i < num_buffers; i++) {
1858        object_buffer_p obj_buffer = buffers[i];
1859        psb__dump_va_buffers_verbose(obj_buffer);
1860
1861        switch (obj_buffer->type) {
1862        case VAPictureParameterBufferType:
1863            /* drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_H264_RenderPicture got VAPictureParameterBuffer\n"); */
1864            vaStatus = psb__H264_process_picture_param(ctx, obj_buffer);
1865            DEBUG_FAILURE;
1866            break;
1867
1868        case VAIQMatrixBufferType:
1869            /* drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_H264_RenderPicture got VAIQMatrixBufferType\n"); */
1870            vaStatus = psb__H264_process_iq_matrix(ctx, obj_buffer);
1871            DEBUG_FAILURE;
1872            break;
1873
1874        case VASliceGroupMapBufferType:
1875            /* drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_H264_RenderPicture got VASliceGroupMapBufferType\n"); */
1876            vaStatus = psb__H264_process_slice_group_map(ctx, obj_buffer);
1877            DEBUG_FAILURE;
1878            break;
1879
1880        case VASliceParameterBufferType:
1881            /* drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_H264_RenderPicture got VASliceParameterBufferType\n"); */
1882            vaStatus = psb__H264_add_slice_param(ctx, obj_buffer);
1883            DEBUG_FAILURE;
1884            break;
1885
1886        case VASliceDataBufferType:
1887        case VAProtectedSliceDataBufferType:
1888            /* drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_H264_RenderPicture got %s\n", SLICEDATA_BUFFER_TYPE(obj_buffer->type)); */
1889            vaStatus = psb__H264_process_slice_data(ctx, obj_buffer);
1890            DEBUG_FAILURE;
1891            break;
1892
1893        default:
1894            vaStatus = VA_STATUS_ERROR_UNKNOWN;
1895            DEBUG_FAILURE;
1896        }
1897        if (vaStatus != VA_STATUS_SUCCESS) {
1898            break;
1899        }
1900    }
1901
1902    return vaStatus;
1903}
1904
1905static VAStatus pnw_H264_EndPicture(
1906    object_context_p obj_context)
1907{
1908    INIT_CONTEXT_H264
1909    psb_surface_p target_surface = ctx->obj_context->current_render_target->psb_surface;
1910    psb_driver_data_p driver_data = obj_context->driver_data;
1911
1912    if (ctx->two_pass_mode) {
1913        psb_buffer_p colocated_target_buffer = psb__H264_lookup_colocated_buffer(ctx, target_surface);
1914        psb_surface_p rotate_surface = ctx->obj_context->current_render_target->psb_surface_rotate;
1915        uint32_t rotation_flags = 0;
1916        uint32_t ext_stride_a = 0;
1917
1918        drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_H264_EndPicture got two pass mode frame\n");
1919        if (CONTEXT_ROTATE(ctx->obj_context)) {
1920            ASSERT(rotate_surface);
1921            REGIO_WRITE_FIELD_LITE(rotation_flags, MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION , ALT_PICTURE_ENABLE, 1);
1922            REGIO_WRITE_FIELD_LITE(rotation_flags, MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION , ROTATION_ROW_STRIDE, rotate_surface->stride_mode);
1923            REGIO_WRITE_FIELD_LITE(rotation_flags, MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION , RECON_WRITE_DISABLE, 0); /* FIXME Always generate Rec */
1924            REGIO_WRITE_FIELD_LITE(rotation_flags, MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION , ROTATION_MODE, GET_SURFACE_INFO_rotate(rotate_surface));
1925        }
1926
1927        REGIO_WRITE_FIELD_LITE(ext_stride_a, MSVDX_CMDS, EXTENDED_ROW_STRIDE, EXT_ROW_STRIDE, target_surface->stride / 64);
1928
1929        /* Issue two pass deblock cmd, HW can handle deblock instead of host when using DE2.x firmware */
1930        if (ctx->deblock_mode == DEBLOCK_STD) {
1931            if (psb_context_submit_hw_deblock(ctx->obj_context,
1932                                              &target_surface->buf,
1933                                              rotate_surface ? (&rotate_surface->buf) : NULL,
1934                                              colocated_target_buffer,
1935                                              ctx->picture_width_mb,
1936                                              ctx->picture_height_mb,
1937                                              rotation_flags,
1938                                              ctx->field_type,
1939                                              ext_stride_a,
1940                                              target_surface->chroma_offset + target_surface->buf.buffer_ofs,
1941                                              rotate_surface ? (rotate_surface->chroma_offset + rotate_surface->buf.buffer_ofs) : 0,
1942                                              ctx->deblock_mode == DEBLOCK_INTRA_OOLD)) {
1943                return VA_STATUS_ERROR_UNKNOWN;
1944            }
1945        } else if (ctx->deblock_mode == DEBLOCK_INTRA_OOLD) {
1946            psb_buffer_p buffer_dst;
1947            uint32_t chroma_offset_dst;
1948
1949            if (CONTEXT_ROTATE(ctx->obj_context) == 0) {
1950                buffer_dst = &target_surface->buf;
1951                chroma_offset_dst = target_surface->chroma_offset;
1952            } else {
1953                if (!rotate_surface) {
1954                    ASSERT(0);
1955                }
1956
1957                buffer_dst = &rotate_surface->buf;
1958                chroma_offset_dst = rotate_surface->chroma_offset;
1959            }
1960
1961            if (psb_context_submit_hw_deblock(ctx->obj_context,
1962                                              target_surface->in_loop_buf,
1963                                              buffer_dst,
1964                                              colocated_target_buffer,
1965                                              ctx->picture_width_mb,
1966                                              ctx->picture_height_mb,
1967                                              rotation_flags,
1968                                              ctx->field_type,
1969                                              ext_stride_a,
1970                                              target_surface->chroma_offset + target_surface->buf.buffer_ofs,
1971                                              chroma_offset_dst,
1972                                              ctx->deblock_mode == DEBLOCK_INTRA_OOLD)) {
1973                return VA_STATUS_ERROR_UNKNOWN;
1974            }
1975        }
1976    }
1977
1978#ifdef PSBVIDEO_MSVDX_EC
1979    /* Sent the HOST_BE_OPP command to detect slice error */
1980    if (driver_data->ec_enabled) {
1981        uint32_t rotation_flags = 0;
1982        uint32_t ext_stride_a = 0;
1983        object_surface_p ec_target;
1984
1985        psb__H264_choose_ec_frames(ctx);
1986        ec_target = ctx->obj_context->ec_target;
1987        REGIO_WRITE_FIELD_LITE(ext_stride_a, MSVDX_CMDS, EXTENDED_ROW_STRIDE, EXT_ROW_STRIDE, target_surface->stride / 64);
1988
1989    /* FIXME ec ignor rotate condition */
1990        if(ec_target)
1991            if (psb_context_submit_host_be_opp(ctx->obj_context,
1992                                          &target_surface->buf,
1993                                          &ec_target->psb_surface->buf,
1994                                          NULL,
1995                                          ctx->picture_width_mb,
1996                                          ctx->picture_height_mb,
1997                                          rotation_flags,
1998                                          ctx->field_type,
1999                                          ext_stride_a,
2000                                          target_surface->chroma_offset + target_surface->buf.buffer_ofs,
2001                                          ec_target->psb_surface->chroma_offset + ec_target->psb_surface->buf.buffer_ofs)) {
2002            return VA_STATUS_ERROR_UNKNOWN;
2003        }
2004    }
2005#endif
2006
2007    if (psb_context_flush_cmdbuf(ctx->obj_context)) {
2008        return VA_STATUS_ERROR_UNKNOWN;
2009    }
2010
2011    if (ctx->pic_params) {
2012        free(ctx->pic_params);
2013        ctx->pic_params = NULL;
2014    }
2015
2016    if (ctx->iq_matrix) {
2017        free(ctx->iq_matrix);
2018        ctx->iq_matrix = NULL;
2019    }
2020
2021    return VA_STATUS_SUCCESS;
2022}
2023
2024struct format_vtable_s pnw_H264_vtable = {
2025queryConfigAttributes:
2026    pnw_H264_QueryConfigAttributes,
2027validateConfig:
2028    pnw_H264_ValidateConfig,
2029createContext:
2030    pnw_H264_CreateContext,
2031destroyContext:
2032    pnw_H264_DestroyContext,
2033beginPicture:
2034    pnw_H264_BeginPicture,
2035renderPicture:
2036    pnw_H264_RenderPicture,
2037endPicture:
2038    pnw_H264_EndPicture
2039};
2040