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