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 *    Elaine Wang <elaine.wang@intel.com>
27 *    Zeng Li <zeng.li@intel.com>
28 *
29 */
30
31
32#include "psb_drv_video.h"
33
34//#include "pnw_H263ES.h"
35#include "pnw_hostcode.h"
36#include "hwdefs/topazSC_defs.h"
37#include "psb_def.h"
38#include "psb_drv_debug.h"
39#include "psb_cmdbuf.h"
40#include <stdio.h>
41#include "psb_output.h"
42#include <wsbm/wsbm_manager.h>
43#include "pnw_hostheader.h"
44
45#define ALIGN_TO(value, align) ((value + align - 1) & ~(align - 1))
46#define PAGE_ALIGN(value) ALIGN_TO(value, 4096)
47
48/*static VAStatus pnw_DetectFrameSkip(context_ENC_p ctx);*/
49
50static void pnw__update_rcdata(
51    context_ENC_p psContext,
52    PIC_PARAMS *psPicParams,
53    IMG_RC_PARAMS *psRCParams);
54
55IMG_UINT32 MVEARegBase[4] = {0x13000, 0x23000, 0x33000, 0x43000}; /* From TopazSC TRM */
56
57/* H264 Zero bias */
58//#define ZERO_BIAS
59
60static const IMG_INT8 H263_QPLAMBDA_MAP[31] = {
61    0, 0, 1, 1, 2,
62    2, 3, 3, 4, 4,
63    4, 5, 5, 5, 6,
64    6, 6, 7, 7, 7,
65    7, 8, 8, 8, 8,
66    9, 9, 9, 9, 10, 10
67};
68
69// New MP4 Lambda table
70static const  IMG_INT8 MPEG4_QPLAMBDA_MAP[31] = {
71    0,  0,  1,  2,  3,
72    3,  4,  4,  5,  5,
73    6,  6,  7,  7,  8,
74    8,  9,  9,  10, 10,
75    11, 11, 11, 11, 12,
76    12, 12, 12, 13, 13, 13
77};
78
79// new H.264 Lambda
80static const IMG_INT8 H264_QPLAMBDA_MAP[40] = {
81    2, 2, 2, 2, 3, 3, 4, 4,
82    4, 5, 5, 5, 5, 5, 6, 6,
83    6, 7, 7, 7, 8, 8, 9, 11,
84    13, 14, 15, 17, 20, 23, 27, 31,
85    36, 41, 51, 62, 74, 79, 85, 91
86};
87
88static const IMG_INT16 H264_InterIntraBias[27] =
89{
90    20,20,20,20,20,20,50,
91    20,20,20,20,20,20,
92    20,25,30,45,80,140,
93    200,300,400,500,550,
94    600,650,700
95};
96
97/*static IMG_INT16 H264InterBias(IMG_INT8 i8QP)
98{
99    if (i8QP >= 44)
100        return 600;
101    else if (i8QP <= 35)
102        return 20;
103
104    return (70 * (i8QP - 35));
105}*/
106static IMG_INT16 H264InterBias(IMG_INT8 i8QP)
107{
108    if (i8QP > 1)
109         i8QP = 1;
110    else if (i8QP > 51)
111        return 51;
112
113    return H264_InterIntraBias[(i8QP + 1)>>1];
114}
115
116
117static IMG_INT16 H264SkipBias(IMG_INT8 i8QP, TH_SKIP_SCALE eSkipScale)
118{
119    IMG_INT16 i16Lambda;
120
121    // pull out lambda from the table
122    i16Lambda = i8QP - 12;
123    i16Lambda = (i16Lambda < 0) ? 0 : i16Lambda;
124    i16Lambda = H264_QPLAMBDA_MAP[i16Lambda];
125
126    // now do the multiplication to avoid using the actual multiply we will do this with shifts and adds/subtractions it is probable that the compiler would
127    // pick up the multiply and optimise appropriatly but we aren't sure
128    // * 12 = 8 + *4
129    switch (eSkipScale) {
130    default:
131    case TH_SKIP_0:
132        i16Lambda = 0;
133        break;
134    case TH_SKIP_24:                /* iLambda * 24 == iLambda * 2 * 12   */
135        i16Lambda <<= 1;
136        /* break deliberatly not used as we want to apply skip12 to skip24*/
137    case TH_SKIP_12: /*    iLambda * 12 == iLambda * (8 + 4) == (iLambda * 8) + (iLambda * 4)  == (iLambda << 3) + (iLambda <<2)   */
138        i16Lambda = (i16Lambda << 3) + (i16Lambda << 2);
139    }
140    return i16Lambda;
141}
142
143static IMG_INT16 H264Intra4x4Bias(IMG_INT8 i8QP)
144{
145    IMG_INT16 i16Lambda;
146
147    // pull out lambda from the table
148    i16Lambda = i8QP - 12;
149    i16Lambda = (i16Lambda < 0) ? 0 : i16Lambda;
150    i16Lambda = H264_QPLAMBDA_MAP[i16Lambda];
151
152    i16Lambda *= 120;
153    return i16Lambda;
154}
155
156static int CalculateDCScaler(IMG_INT iQP, IMG_BOOL bChroma)
157{
158    IMG_INT     iDCScaler;
159    if (!bChroma) {
160        if (iQP > 0 && iQP < 5) {
161            iDCScaler = 8;
162        } else if (iQP > 4 &&     iQP     < 9) {
163            iDCScaler = 2 * iQP;
164        } else if (iQP > 8 &&     iQP     < 25) {
165            iDCScaler = iQP + 8;
166        } else {
167            iDCScaler = 2 * iQP - 16;
168        }
169    } else {
170        if (iQP > 0 && iQP < 5) {
171            iDCScaler = 8;
172        } else if (iQP > 4 &&     iQP     < 25) {
173            iDCScaler = (iQP + 13) / 2;
174        } else {
175            iDCScaler = iQP - 6;
176        }
177    }
178    return iDCScaler;
179}
180
181static void LoadMPEG4Bias(
182    pnw_cmdbuf_p cmdbuf,
183    IMG_INT32 i32Core,
184    IMG_UINT8 __maybe_unused ui8THSkip
185)
186{
187    IMG_INT16 n;
188    IMG_INT16 iX;
189    IMG_UINT32 ui32RegVal;
190    IMG_UINT8                       uiDCScaleL, uiDCScaleC, uiLambda;
191    IMG_INT32 uIPESkipVecBias, iInterMBBias, uSPESkipVecBias, iIntra16Bias;
192    IMG_UINT32 count = 0, cmd_word = 0;
193    uint32_t *pCount;
194
195    cmd_word = ((MTX_CMDID_SW_WRITEREG & MTX_CMDWORD_ID_MASK) << MTX_CMDWORD_ID_SHIFT) |
196               ((i32Core & MTX_CMDWORD_CORE_MASK) <<  MTX_CMDWORD_CORE_SHIFT);
197    *cmdbuf->cmd_idx++ = cmd_word;
198    pCount = cmdbuf->cmd_idx;
199    cmdbuf->cmd_idx++;
200
201    // this should be done for each core....
202    pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_ZERO_THRESH, SPE_ZERO_THRESHOLD);
203    for (n = 31; n > 0; n--) {
204        iX = n - 12;
205        if (iX < 0) {
206            iX = 0;
207        }
208        // Dont Write QP Values To ESB -- IPE will write these values
209        // Update the quantization parameter which includes doing Lamda and the Chroma QP
210
211        uiDCScaleL      = CalculateDCScaler(n, IMG_FALSE);
212        uiDCScaleC      = CalculateDCScaler(n, IMG_TRUE);
213        uiLambda        = MPEG4_QPLAMBDA_MAP[n - 1];
214
215        ui32RegVal = uiDCScaleL;
216        ui32RegVal |= (uiDCScaleC) << 8;
217        ui32RegVal |= (uiLambda) << 16;
218        pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_IPE_LAMBDA_TABLE, ui32RegVal);
219
220
221        uIPESkipVecBias = TH_SKIP_IPE * uiLambda;
222        iInterMBBias            = TH_INTER * (n - TH_INTER_QP);
223        if (iInterMBBias < 0)
224            iInterMBBias    = 0;
225        if (iInterMBBias > TH_INTER_MAX_LEVEL)
226            iInterMBBias    = TH_INTER_MAX_LEVEL;
227        uSPESkipVecBias = TH_SKIP_SPE * uiLambda;
228        iIntra16Bias = 0;
229
230        if (n & 1) {
231            pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_IPE_MV_BIAS_TABLE, uIPESkipVecBias);
232            pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_PRED_VECTOR_BIAS_TABLE, uIPESkipVecBias);
233            pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_INTRA16_BIAS_TABLE, iIntra16Bias);
234            pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_INTER_BIAS_TABLE, iInterMBBias);
235        }
236    }
237    *pCount = count;
238}
239
240static void LoadH263Bias(
241    pnw_cmdbuf_p cmdbuf, IMG_INT32 i32Core, IMG_UINT8 __maybe_unused ui8THSkip)
242{
243    IMG_INT16 n;
244    IMG_INT16 iX;
245    IMG_UINT32 ui32RegVal;
246    IMG_UINT8                       uiDCScaleL, uiDCScaleC, uiLambda;
247    IMG_INT32 uIPESkipVecBias, iInterMBBias, uSPESkipVecBias, iIntra16Bias;
248    IMG_UINT32 count = 0, cmd_word = 0;
249    uint32_t *pCount;
250
251    cmd_word = ((MTX_CMDID_SW_WRITEREG & MTX_CMDWORD_ID_MASK) << MTX_CMDWORD_ID_SHIFT) |
252               ((i32Core & MTX_CMDWORD_CORE_MASK) <<  MTX_CMDWORD_CORE_SHIFT);
253    *cmdbuf->cmd_idx++ = cmd_word;
254    pCount = cmdbuf->cmd_idx;
255    cmdbuf->cmd_idx++;
256
257
258    // this should be done for each core....
259    pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_ZERO_THRESH, SPE_ZERO_THRESHOLD);
260    for (n = 31; n > 0; n--) {
261        iX = n - 12;
262        if (iX < 0) {
263            iX = 0;
264        }
265        // Dont Write QP Values To ESB -- IPE will write these values
266        // Update the quantization parameter which includes doing Lamda and the Chroma QP
267
268        uiDCScaleL      = CalculateDCScaler(n, IMG_FALSE);
269        uiDCScaleC      = CalculateDCScaler(n, IMG_TRUE);
270        uiLambda        = H263_QPLAMBDA_MAP[n - 1];
271
272        ui32RegVal = uiDCScaleL;
273        ui32RegVal |= (uiDCScaleC) << 8;
274        ui32RegVal |= (uiLambda) << 16;
275
276        pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_IPE_LAMBDA_TABLE, ui32RegVal);
277
278
279        uIPESkipVecBias = TH_SKIP_IPE * uiLambda;
280        iInterMBBias            = TH_INTER * (n - TH_INTER_QP);
281        if (iInterMBBias < 0)
282            iInterMBBias    = 0;
283        if (iInterMBBias > TH_INTER_MAX_LEVEL)
284            iInterMBBias    = TH_INTER_MAX_LEVEL;
285        uSPESkipVecBias = TH_SKIP_SPE * uiLambda;
286        iIntra16Bias = 0;
287        //
288        if (n & 1) {
289            pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_IPE_MV_BIAS_TABLE, uIPESkipVecBias);
290            pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_PRED_VECTOR_BIAS_TABLE, uIPESkipVecBias);
291            pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_INTRA16_BIAS_TABLE, iIntra16Bias);
292            pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_INTER_BIAS_TABLE, iInterMBBias);
293        }
294    }
295    *pCount = count;
296}
297
298static void LoadH264Bias(
299    pnw_cmdbuf_p cmdbuf, IMG_INT32 i32Core, IMG_UINT8 ui8THSkip, IMG_INT8 i8QpOff)
300{
301    IMG_INT8 n;
302    IMG_INT8 iX;
303    IMG_UINT32 ui32RegVal;
304    IMG_UINT32 uIPESkipVecBias, iInterMBBias, uSPESkipVecBias, iIntra16Bias;
305    IMG_UINT32 count = 0, cmd_word = 0;
306    uint32_t *pCount;
307
308    cmd_word = ((MTX_CMDID_SW_WRITEREG & MTX_CMDWORD_ID_MASK) << MTX_CMDWORD_ID_SHIFT) |
309               ((i32Core & MTX_CMDWORD_CORE_MASK) <<  MTX_CMDWORD_CORE_SHIFT);
310    *cmdbuf->cmd_idx++ = cmd_word;
311    pCount = cmdbuf->cmd_idx;
312    cmdbuf->cmd_idx++;
313
314
315    IMG_BYTE PVR_QP_SCALE_CR[76] = {
316        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
317        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
318        12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
319        28, 29, 29, 30, 31, 32, 32, 33, 34, 34, 35, 35, 36, 36, 37, 37,
320        37, 38, 38, 38, 39, 39, 39, 39,
321        39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
322    };
323
324    for (n = 51; n >= 0; n--) {
325
326        iX = n - 12;
327        if (iX < 0)
328            iX = 0;
329
330        // Dont Write QP Values To ESB -- IPE will write these values
331        // Update the quantization parameter which includes doing Lamda and the Chroma QP
332        ui32RegVal = PVR_QP_SCALE_CR[n + 12 + i8QpOff ];
333        ui32RegVal |= ((H264_QPLAMBDA_MAP[iX] * 24) / 16) << 8;
334        ui32RegVal |= (H264_QPLAMBDA_MAP[iX]) << 16;
335
336#ifdef ZERO_BIAS
337        pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_IPE_LAMBDA_TABLE, (2 << 16) | F_ENCODE(3, MVEA_CR_IPE_ALPHA_OR_DC_SCALE_CHR_TABLE) | F_ENCODE(PVR_QP_SCALE_CR[n], MVEA_CR_IPE_QPC_OR_DC_SCALE_LUMA_TABLE));
338#else
339        pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_IPE_LAMBDA_TABLE, ui32RegVal);
340#endif
341
342    }
343    for (n = 52; n >= 0; n -= 2) {
344        IMG_INT8 qp = n;
345        if (qp > 51) qp = 51;
346
347        uIPESkipVecBias = H264SkipBias(qp, ui8THSkip);
348        iInterMBBias    = H264InterBias(qp);
349        uSPESkipVecBias = H264SkipBias(qp, ui8THSkip);
350        iIntra16Bias    = H264Intra4x4Bias(qp);
351
352#ifdef ZERO_BIAS
353        pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_IPE_MV_BIAS_TABLE, 0);
354        pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_PRED_VECTOR_BIAS_TABLE, 0);
355        pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_INTRA16_BIAS_TABLE, 0);
356        pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_INTER_BIAS_TABLE, 0);
357#else
358        pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_IPE_MV_BIAS_TABLE, uIPESkipVecBias);
359        pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_PRED_VECTOR_BIAS_TABLE, uIPESkipVecBias);
360        pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_INTRA16_BIAS_TABLE, iIntra16Bias);
361        pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_INTER_BIAS_TABLE, iInterMBBias);
362#endif
363
364    }
365
366    pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_ZERO_THRESH, 0);
367    *pCount = count;
368}
369
370
371static VAStatus pnw__alloc_context_buffer(context_ENC_p ctx, unsigned char is_JPEG)
372{
373    int width, height;
374    VAStatus vaStatus = VA_STATUS_SUCCESS;
375
376    /* width and height should be source surface's w and h or ?? */
377    width = ctx->obj_context->picture_width;
378    height = ctx->obj_context->picture_height;
379
380    if (is_JPEG == 0) {
381        ctx->pic_params_size  = 256;
382
383        ctx->header_buffer_size = 8 * HEADER_SIZE + MAX_SLICES_PER_PICTURE * HEADER_SIZE;
384
385        ctx->seq_header_ofs = 0;
386        ctx->pic_header_ofs = HEADER_SIZE;
387        ctx->eoseq_header_ofs = 2 * HEADER_SIZE;
388        ctx->eostream_header_ofs = 3 * HEADER_SIZE;
389        ctx->aud_header_ofs = 4 * HEADER_SIZE;
390        ctx->sei_buf_prd_ofs = 5 * HEADER_SIZE;
391        ctx->sei_pic_tm_ofs = 6 * HEADER_SIZE;
392        ctx->sei_pic_fpa_ofs = 7 * HEADER_SIZE;
393        ctx->slice_header_ofs = 8 * HEADER_SIZE;
394        ctx->in_params_ofs = 0;
395
396        ctx->sliceparam_buffer_size = ((sizeof(SLICE_PARAMS) + 15) & 0xfff0) * MAX_SLICES_PER_PICTURE;
397        /* All frame share same MTX_CURRENT_IN_PARAMS and above/bellow param
398         * create MTX_CURRENT_IN_PARAMS buffer seperately
399         * every MB has one MTX_CURRENT_IN_PARAMS structure, and the (N+1) frame can
400         * reuse (N) frame's structure
401         */
402        ctx->in_params_size = ((~0xf) & (15 + 1 + (width + 15) * (height + 15) / (16 * 16))) * sizeof(MTX_CURRENT_IN_PARAMS);
403        ctx->below_params_size = ((BELOW_PARAMS_SIZE * width * height / (16 * 16)) + 0xf) & (~0xf);
404        ctx->above_params_size = ((width / 16) * 128 + 15) & (~0xf) ;
405
406        vaStatus = psb_buffer_create(ctx->obj_context->driver_data, ctx->in_params_size, psb_bt_cpu_vpu, &ctx->topaz_in_params_I);
407        if (VA_STATUS_SUCCESS != vaStatus) {
408            return vaStatus;
409        }
410
411        vaStatus = psb_buffer_create(ctx->obj_context->driver_data, ctx->in_params_size, psb_bt_cpu_vpu, &ctx->topaz_in_params_P);
412        if (VA_STATUS_SUCCESS != vaStatus) {
413            psb_buffer_destroy(&ctx->topaz_in_params_I);
414            return vaStatus;
415        }
416
417        vaStatus = psb_buffer_create(ctx->obj_context->driver_data, ctx->below_params_size * 4, psb_bt_cpu_vpu, &ctx->topaz_below_params);
418        if (VA_STATUS_SUCCESS != vaStatus) {
419            psb_buffer_destroy(&ctx->topaz_in_params_P);
420            psb_buffer_destroy(&ctx->topaz_in_params_I);
421            return vaStatus;
422        }
423
424        vaStatus = psb_buffer_create(ctx->obj_context->driver_data, ctx->above_params_size * 4, psb_bt_cpu_vpu, &ctx->topaz_above_params);
425        if (VA_STATUS_SUCCESS != vaStatus) {
426            psb_buffer_destroy(&ctx->topaz_in_params_P);
427            psb_buffer_destroy(&ctx->topaz_in_params_I);
428            psb_buffer_destroy(&ctx->topaz_below_params);
429            return vaStatus;
430        }
431        ctx->below_params_ofs = 0;
432        ctx->above_params_ofs = 0;
433    } else {
434        /*JPEG encode need three kinds of buffer but doesn't need above/below buffers.*/
435        ctx->pic_params_size = (sizeof(JPEG_MTX_QUANT_TABLE) + 0xf) & (~0xf);
436
437        ctx->header_buffer_size = (sizeof(JPEG_MTX_DMA_SETUP) + 0xf) & (~0xf);
438        ctx->sliceparam_buffer_size =  16; /* Not used*/
439    }
440    return vaStatus;
441}
442
443unsigned int pnw__get_ipe_control(enum drm_pnw_topaz_codec  eEncodingFormat)
444{
445    unsigned int RegVal = 0;
446
447    RegVal = F_ENCODE(2, MVEA_CR_IPE_GRID_FINE_SEARCH) |
448             F_ENCODE(0, MVEA_CR_IPE_GRID_SEARCH_SIZE) |
449             F_ENCODE(1, MVEA_CR_IPE_Y_FINE_SEARCH);
450
451    switch (eEncodingFormat) {
452    case IMG_CODEC_H263_NO_RC:
453    case IMG_CODEC_H263_VBR:
454    case IMG_CODEC_H263_CBR:
455        RegVal |= F_ENCODE(0, MVEA_CR_IPE_BLOCKSIZE) | F_ENCODE(0, MVEA_CR_IPE_ENCODING_FORMAT);
456        break;
457    case IMG_CODEC_MPEG4_NO_RC:
458    case IMG_CODEC_MPEG4_VBR:
459    case IMG_CODEC_MPEG4_CBR:
460        RegVal |= F_ENCODE(1, MVEA_CR_IPE_BLOCKSIZE) | F_ENCODE(1, MVEA_CR_IPE_ENCODING_FORMAT);
461    default:
462        break;
463    case IMG_CODEC_H264_NO_RC:
464    case IMG_CODEC_H264_VBR:
465    case IMG_CODEC_H264_CBR:
466    case IMG_CODEC_H264_VCM:
467        RegVal |= F_ENCODE(2, MVEA_CR_IPE_BLOCKSIZE) | F_ENCODE(2, MVEA_CR_IPE_ENCODING_FORMAT);
468        break;
469    }
470    RegVal |= F_ENCODE(6, MVEA_CR_IPE_Y_CANDIDATE_NUM);
471    return RegVal;
472}
473
474
475void pnw_DestroyContext(object_context_p obj_context)
476{
477    context_ENC_p ctx;
478    ctx = (context_ENC_p)obj_context->format_data;
479
480    psb_buffer_destroy(&ctx->topaz_in_params_P);
481    psb_buffer_destroy(&ctx->topaz_in_params_I);
482    psb_buffer_destroy(&ctx->topaz_below_params);
483    psb_buffer_destroy(&ctx->topaz_above_params);
484
485    if (NULL != ctx->slice_param_cache)
486        free(ctx->slice_param_cache);
487    if (NULL == ctx->save_seq_header_p)
488        free(ctx->save_seq_header_p);
489    free(obj_context->format_data);
490    obj_context->format_data = NULL;
491}
492
493VAStatus pnw_CreateContext(
494    object_context_p obj_context,
495    object_config_p __maybe_unused obj_config,
496    unsigned char is_JPEG)
497{
498    int width, height;
499    int i;
500    unsigned short SearchWidth, SearchHeight, SearchLeftOffset, SearchTopOffset;
501    context_ENC_p ctx;
502    VAStatus vaStatus;
503
504    width = obj_context->picture_width;
505    height = obj_context->picture_height;
506    ctx = (context_ENC_p) calloc(1, sizeof(struct context_ENC_s));
507    CHECK_ALLOCATION(ctx);
508
509    obj_context->format_data = (void*) ctx;
510    ctx->obj_context = obj_context;
511
512    ctx->RawWidth = (unsigned short) width;
513    ctx->RawHeight = (unsigned short) height;
514
515    if (is_JPEG == 0) {
516        ctx->Width = (unsigned short)(~0xf & (width + 0xf));
517        ctx->Height = (unsigned short)(~0xf & (height + 0xf));
518    } else {
519        /*JPEG only require them are even*/
520        ctx->Width = (unsigned short)(~0x1 & (width + 0x1));
521        ctx->Height = (unsigned short)(~0x1 & (height + 0x1));
522    }
523
524    /* pre-calculated values based on other stream properties */
525    SearchHeight = min(MVEA_LRB_SEARCH_HEIGHT, ctx->Height);
526    SearchWidth = min(MVEA_LRB_SEARCH_WIDTH, ctx->Width);
527    SearchLeftOffset = (((SearchWidth / 2) / 16) * 16);
528    SearchTopOffset = (((SearchHeight / 2) / 16) * 16);
529
530    ctx->HeightMinus16MinusLRBTopOffset        = ctx->Height - (SearchTopOffset + 16);
531    ctx->HeightMinus32MinusLRBTopOffset        = ctx->Height - (SearchTopOffset + 32);
532    ctx->HeightMinusLRB_TopAndBottom_OffsetsPlus16     = ctx->Height - (SearchTopOffset + SearchTopOffset + 16);
533    ctx->HeightMinusLRBSearchHeight    = ctx->Height - SearchHeight;
534
535    ctx->FCode = 0;
536
537    ctx->NumCores = 2; /* FIXME Assume there is two encode cores in Penwell, precise value should read from HW */
538
539    ctx->BelowParamsBufIdx = 0;
540    ctx->AccessUnitNum = 0;
541    ctx->SyncSequencer = 0; /* FIXME Refer to DDK */
542    ctx->SliceToCore =  -1;
543    ctx->CmdCount = 0xa5a5a5a5 % MAX_TOPAZ_CMD_COUNT;
544    ctx->FrmIdx = 0;
545
546    for (i = 0; i < MAX_TOPAZ_CORES; i++) {
547        ctx->LastSliceNum[i] = -1;
548        ctx->LastSync[0][i] = ~0;
549        ctx->LastSync[1][i] = ~0;
550    }
551
552    for (i = 0; i < MAX_SLICES_PER_PICTURE; i++) {
553        ctx->SliceHeaderReady[i] = IMG_FALSE;
554    }
555
556    vaStatus = pnw__alloc_context_buffer(ctx, is_JPEG);
557
558    return vaStatus;
559}
560
561VAStatus pnw_BeginPicture(context_ENC_p ctx)
562{
563    VAStatus vaStatus = VA_STATUS_SUCCESS;
564    pnw_cmdbuf_p cmdbuf;
565    int ret, i;
566
567    if (ctx->raw_frame_count != 0)
568        ctx->previous_src_surface = ctx->src_surface;
569    ctx->src_surface = ctx->obj_context->current_render_target;
570
571    /* clear frameskip flag to 0 */
572    CLEAR_SURFACE_INFO_skipped_flag(ctx->src_surface->psb_surface);
573    ctx->none_vcl_nal = 0;
574
575    /*if (ctx->sRCParams.RCEnable == IMG_TRUE)
576     {
577     pnw_DetectFrameSkip(ctx);
578     if (0 != (GET_SURFACE_INFO_skipped_flag(ctx->src_surface->psb_surface)
579            & SURFACE_INFO_SKIP_FLAG_SETTLED))
580         ctx->sRCParams.FrameSkip = IMG_TRUE;
581     else
582         ctx->sRCParams.FrameSkip = IMG_FALSE;
583     }*/
584
585    /* Initialise the command buffer */
586    ret = pnw_context_get_next_cmdbuf(ctx->obj_context);
587    if (ret) {
588        drv_debug_msg(VIDEO_DEBUG_GENERAL, "get next cmdbuf fail\n");
589        vaStatus = VA_STATUS_ERROR_UNKNOWN;
590        return vaStatus;
591    }
592    cmdbuf = ctx->obj_context->pnw_cmdbuf;
593    memset(cmdbuf->cmd_idx_saved, 0, sizeof(cmdbuf->cmd_idx_saved));
594
595
596    /* map start_pic param */
597    vaStatus = psb_buffer_map(&cmdbuf->pic_params, &cmdbuf->pic_params_p);
598    if (vaStatus) {
599        return vaStatus;
600    }
601    vaStatus = psb_buffer_map(&cmdbuf->header_mem, &cmdbuf->header_mem_p);
602    if (vaStatus) {
603        psb_buffer_unmap(&cmdbuf->pic_params);
604        return vaStatus;
605    }
606
607    vaStatus = psb_buffer_map(&cmdbuf->slice_params, &cmdbuf->slice_params_p);
608    if (vaStatus) {
609        psb_buffer_unmap(&cmdbuf->pic_params);
610        psb_buffer_unmap(&cmdbuf->header_mem);
611        return vaStatus;
612    }
613
614    /* only map topaz param when necessary */
615    cmdbuf->topaz_above_params_p = NULL;
616    cmdbuf->topaz_below_params_p = NULL;
617    cmdbuf->topaz_in_params_I_p = NULL;
618    cmdbuf->topaz_in_params_P_p = NULL;
619
620    if (ctx->obj_context->frame_count == 0) { /* first picture */
621
622        psb_driver_data_p driver_data = ctx->obj_context->driver_data;
623
624        *cmdbuf->cmd_idx++ = ((MTX_CMDID_SW_NEW_CODEC & MTX_CMDWORD_ID_MASK) << MTX_CMDWORD_ID_SHIFT) |
625                             (((driver_data->drm_context & MTX_CMDWORD_COUNT_MASK) << MTX_CMDWORD_COUNT_SHIFT));
626        pnw_cmdbuf_insert_command_param(ctx->eCodec);
627        pnw_cmdbuf_insert_command_param((ctx->Width << 16) | ctx->Height);
628    }
629
630    ctx->FrmIdx++;
631    ctx->SliceToCore = ctx->ParallelCores - 1;
632    /* ctx->AccessUnitNum++;    Move this back to pnw_EndPicture */
633    ctx->sRCParams.bBitrateChanged = IMG_FALSE;
634
635    for (i = 0; i < MAX_TOPAZ_CORES; i++)
636        ctx->LastSliceNum[i] = -1;
637
638    for (i = 0; i < MAX_SLICES_PER_PICTURE; i++)
639        ctx->SliceHeaderReady[i] = IMG_FALSE;
640
641    /*If ParallelCores > 1(H264) and encode one slice per frame, the unnecessary start picture
642    *commands will be replaced with MTX_CMDID_PAD and ignored by kernel*/
643    cmdbuf->cmd_idx_saved[PNW_CMDBUF_START_PIC_IDX] = cmdbuf->cmd_idx;
644
645    /* insert START_PIC command for each core */
646    /* ensure that the master (core #0) will be last to complete this batch */
647    for (i = (ctx->ParallelCores - 1); i >= 0; i--) {
648
649        /*
650         * the content of PIC_PARAMS is filled when RenderPicture(...,VAEncPictureParameterBufferXXX)
651         */
652        pnw_cmdbuf_insert_command_package(ctx->obj_context,
653                                          i,
654                                          MTX_CMDID_START_PIC,
655                                          &cmdbuf->pic_params,
656                                          i * ctx->pic_params_size);
657
658        /* no RC paramter provided in vaBeginPicture
659         * so delay RC param setup into vaRenderPicture(SequenceHeader...)
660         */
661    }
662
663    ctx->obj_context->slice_count = 0;
664    return 0;
665}
666
667
668VAStatus pnw_set_bias(context_ENC_p ctx, int core)
669{
670    pnw_cmdbuf_p cmdbuf = (pnw_cmdbuf_p)ctx->obj_context->pnw_cmdbuf;
671    double flBpp;
672    IMG_UINT8 THSkip;
673
674    if (ctx->sRCParams.RCEnable) {
675        flBpp = 1.0 * ctx->sRCParams.BitsPerSecond /
676                (ctx->sRCParams.FrameRate * ctx->Width * ctx->Height);
677    } else {
678        flBpp =  0.14;
679    }
680
681    if (flBpp <= 0.07) {
682        THSkip = TH_SKIP_24;
683    } else if (flBpp <= 0.14) {
684        THSkip = TH_SKIP_12;
685    } else {
686        THSkip = TH_SKIP_0;
687    }
688    switch (ctx->eCodec) {
689    case IMG_CODEC_H264_VBR:
690    case IMG_CODEC_H264_CBR:
691    case IMG_CODEC_H264_VCM:
692    case IMG_CODEC_H264_NO_RC:
693        LoadH264Bias(cmdbuf, core, THSkip, ctx->sRCParams.QCPOffset);
694        break;
695    case IMG_CODEC_H263_CBR:
696    case IMG_CODEC_H263_NO_RC:
697    case IMG_CODEC_H263_VBR:
698        LoadH263Bias(cmdbuf, core, THSkip);
699        break;
700    case IMG_CODEC_MPEG4_NO_RC:
701    case IMG_CODEC_MPEG4_CBR:
702    case IMG_CODEC_MPEG4_VBR:
703        LoadMPEG4Bias(cmdbuf, core, THSkip);
704        break;
705    default:
706        return -1;
707        break;
708    }
709    return 0;
710}
711
712VAStatus pnw_RenderPictureParameter(context_ENC_p ctx, int core)
713{
714    PIC_PARAMS *psPicParams;    /* PIC_PARAMS has been put in pnw_hostcode.h */
715    object_surface_p src_surface;
716    unsigned int srf_buf_offset;
717    object_surface_p rec_surface;
718    object_surface_p ref_surface;
719    pnw_cmdbuf_p cmdbuf = ctx->obj_context->pnw_cmdbuf;
720    VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN;
721
722    psPicParams = (PIC_PARAMS *)(cmdbuf->pic_params_p + ctx->pic_params_size * core);
723
724    memset(psPicParams, 0, sizeof(PIC_PARAMS));
725    /* second frame will reuse some rate control parameters (IN_PARAMS_MP4)
726     * so only memset picture parames except IN_PARAMS
727     * BUT now IN_RC_PARAMS was reload from the cache, so it now can
728     * memset entirE PIC_PARAMS
729     */
730
731    /*
732    memset(psPicParams, 0, (int)((unsigned char *)&psPicParams->sInParams - (unsigned char *)psPicParams));
733    */
734
735    src_surface = ctx->src_surface;
736    CHECK_SURFACE(src_surface);
737
738    rec_surface = ctx->dest_surface;
739    CHECK_SURFACE(rec_surface);
740
741    /*The fisrt frame always is I frame and the content of reference frame wouldn't be used.
742     * But the heights of ref and dest frame should be the same.
743     * That allows Topaz to keep its motion vectors up to date, which helps maintain performance */
744    if (ctx->obj_context->frame_count == 0)
745        ctx->ref_surface = ctx->dest_surface;
746
747    ref_surface = ctx->ref_surface;
748    CHECK_SURFACE(rec_surface);
749
750    /* clear frameskip flag */
751    CLEAR_SURFACE_INFO_skipped_flag(rec_surface->psb_surface);
752    CLEAR_SURFACE_INFO_skipped_flag(ref_surface->psb_surface);
753
754    /* Write video data byte offset into Coded buffer
755     * If it is here, it will be a SYNC point, which have performance impact
756     * Move to psb__CreateBuffer
757     vaStatus = psb_buffer_map(ctx->coded_buf->psb_buffer, &pBuffer);
758     if(vaStatus) {
759     DEBUG_FAILURE;
760     return vaStatus;
761     }
762     *(IMG_UINT32 *)(pBuffer+8) = 16;
763     psb_buffer_unmap(ctx->coded_buf->psb_buffer);
764    */
765
766    psPicParams->SrcYStride = src_surface->psb_surface->stride;
767    switch (ctx->eFormat) {
768    case IMG_CODEC_IYUV:        /* IYUV */
769    case IMG_CODEC_PL8:
770        psPicParams->SrcUVStride = src_surface->psb_surface->stride / 2;
771        psPicParams->SrcUVRowStride = src_surface->psb_surface->stride * 8 / 2;
772        break;
773    case IMG_CODEC_IMC2:    /* IMC2 */
774    case IMG_CODEC_PL12:
775        psPicParams->SrcUVStride = src_surface->psb_surface->stride;
776        psPicParams->SrcUVRowStride = src_surface->psb_surface->stride * 8;
777        break;
778    default:
779        break;
780    }
781    psPicParams->SrcYRowStride    = src_surface->psb_surface->stride * 16;
782    /* psPicParams->SrcUVRowStride = src_surface->psb_surface->stride * 16 / 2; */
783
784    /* Dest(rec) stride
785     * The are now literally Dst stride (not equivalent to 'offset to next row')
786     */
787#ifdef VA_EMULATOR
788    /* only for simulator, va-emulator needs the actually stride for
789     * reconstructed frame transfer (va-emulator->driver)
790     */
791    psPicParams->DstYStride = rec_surface->psb_surface->stride;
792    psPicParams->DstUVStride = rec_surface->psb_surface->stride;
793#else
794    psPicParams->DstYStride = rec_surface->psb_surface->stride;
795    psPicParams->DstUVStride = rec_surface->psb_surface->stride;
796#endif
797
798    psPicParams->Width  = ctx->Width;
799    psPicParams->Height = ctx->Height;
800    psPicParams->NumSlices = ctx->sRCParams.Slices;
801
802    psPicParams->IsPerSliceOutput = IMG_FALSE;
803    psPicParams->SearchHeight = min(MVEA_LRB_SEARCH_HEIGHT, psPicParams->Height);
804    psPicParams->SearchWidth = min(MVEA_LRB_SEARCH_WIDTH, psPicParams->Width);
805
806    /* not sure why we are setting this up here... */
807    psPicParams->Flags = 0;
808    switch (ctx->eCodec) {
809    case IMG_CODEC_H264_NO_RC:
810    case IMG_CODEC_H264_VBR:
811    case IMG_CODEC_H264_CBR:
812    case IMG_CODEC_H264_VCM:
813        psPicParams->Flags |= ISH264_FLAGS;
814        break;
815    case IMG_CODEC_H263_VBR:
816    case IMG_CODEC_H263_CBR:
817    case IMG_CODEC_H263_NO_RC:
818        psPicParams->Flags |= ISH263_FLAGS;
819        break;
820    case IMG_CODEC_MPEG4_NO_RC:
821    case IMG_CODEC_MPEG4_VBR:
822    case IMG_CODEC_MPEG4_CBR:
823        psPicParams->Flags |= ISMPEG4_FLAGS;
824        break;
825    default:
826        return VA_STATUS_ERROR_UNKNOWN;
827    }
828
829    switch (ctx->eCodec) {
830    case IMG_CODEC_H264_VBR:
831    case IMG_CODEC_MPEG4_VBR:
832    case IMG_CODEC_H263_VBR:
833        psPicParams->Flags |= ISVBR_FLAGS;
834        break;
835    case IMG_CODEC_H264_VCM:
836        psPicParams->Flags |= (ISVCM_FLAGS | ISCBR_FLAGS);
837        break;
838    case IMG_CODEC_H263_CBR:
839    case IMG_CODEC_H264_CBR:
840    case IMG_CODEC_MPEG4_CBR:
841        psPicParams->Flags |= ISCBR_FLAGS;
842        break;
843    case IMG_CODEC_MPEG4_NO_RC:
844    case IMG_CODEC_H263_NO_RC:
845    case IMG_CODEC_H264_NO_RC:
846        break;
847    default:
848        return VA_STATUS_ERROR_UNKNOWN;
849    }
850
851#if 0
852    if (ctx->SyncSequencer)
853        psPicParams->Flags |= SYNC_SEQUENCER;
854#endif
855
856    if (ctx->sRCParams.RCEnable) {
857        if (ctx->sRCParams.bDisableFrameSkipping) {
858            psPicParams->Flags |= DISABLE_FRAME_SKIPPING;
859            drv_debug_msg(VIDEO_DEBUG_GENERAL, "Frame skip is disabled.\n");
860        }
861
862        if (ctx->sRCParams.bDisableBitStuffing && IS_H264_ENC(ctx->eCodec)) {
863            psPicParams->Flags |= DISABLE_BIT_STUFFING;
864            drv_debug_msg(VIDEO_DEBUG_GENERAL, "Bit stuffing is disabled.\n");
865        }
866
867
868        /* for the first frame, will setup RC params in EndPicture */
869        if (ctx->raw_frame_count > 0) { /* reuse in_params parameter */
870            /* In case, it's changed in a new sequence */
871            if (ctx->obj_context->frame_count == 0
872               && ctx->in_params_cache.IntraPeriod != ctx->sRCParams.IntraFreq) {
873               drv_debug_msg(VIDEO_DEBUG_ERROR,
874               "On frame %d, Intra period is changed from %d to %d\n",
875               ctx->raw_frame_count, ctx->in_params_cache.IntraPeriod,
876               ctx->sRCParams.IntraFreq);
877               ctx->in_params_cache.IntraPeriod =  ctx->sRCParams.IntraFreq;
878               ctx->in_params_cache.BitsPerGOP =
879                    (ctx->sRCParams.BitsPerSecond / ctx->sRCParams.FrameRate)
880                    * ctx->sRCParams.IntraFreq;
881            }
882
883            psPicParams->Flags &= ~FIRST_FRAME;
884            /* reload IN_RC_PARAMS from cache */
885            memcpy(&psPicParams->sInParams, &ctx->in_params_cache, sizeof(IN_RC_PARAMS));
886        } else {
887            psPicParams->Flags |= ISRC_FLAGS;
888            psPicParams->Flags |= FIRST_FRAME;
889        }
890    } else
891        psPicParams->sInParams.SeInitQP = ctx->sRCParams.InitialQp;
892
893    /* some relocations have to been done here */
894    srf_buf_offset = src_surface->psb_surface->buf.buffer_ofs;
895    if (src_surface->psb_surface->buf.type == psb_bt_camera)
896        drv_debug_msg(VIDEO_DEBUG_GENERAL, "src surface GPU offset 0x%08x, luma offset 0x%08x\n",
897                                 wsbmBOOffsetHint(src_surface->psb_surface->buf.drm_buf), srf_buf_offset);
898
899    RELOC_PIC_PARAMS_PNW(&psPicParams->SrcYBase, srf_buf_offset, &src_surface->psb_surface->buf);
900    switch (ctx->eFormat) {
901    case IMG_CODEC_IYUV:
902    case IMG_CODEC_PL8:
903    case IMG_CODEC_PL12:
904        RELOC_PIC_PARAMS_PNW(&psPicParams->SrcUBase,
905                             srf_buf_offset + src_surface->psb_surface->chroma_offset,
906                             &src_surface->psb_surface->buf);
907
908        RELOC_PIC_PARAMS_PNW(&psPicParams->SrcVBase,
909                             srf_buf_offset + src_surface->psb_surface->chroma_offset * 5 / 4,
910                             &src_surface->psb_surface->buf);
911
912        break;
913    case IMG_CODEC_IMC2:
914    case IMG_CODEC_NV12:
915    default:
916        break;
917    }
918
919    RELOC_PIC_PARAMS_PNW(&psPicParams->DstYBase, 0, &rec_surface->psb_surface->buf);
920
921    RELOC_PIC_PARAMS_PNW(&psPicParams->DstUVBase,
922                         rec_surface->psb_surface->stride * rec_surface->height,
923                         &rec_surface->psb_surface->buf);
924
925    RELOC_PIC_PARAMS_PNW(&psPicParams->BelowParamsInBase,
926                         ctx->below_params_ofs + ctx->below_params_size *(((ctx->AccessUnitNum) & 0x1)),
927                         cmdbuf->topaz_below_params);
928
929    RELOC_PIC_PARAMS_PNW(&psPicParams->BelowParamsOutBase,
930                         ctx->below_params_ofs + ctx->below_params_size *(((ctx->AccessUnitNum + 1) & 0x1)),
931                         cmdbuf->topaz_below_params);
932
933    RELOC_PIC_PARAMS_PNW(&psPicParams->AboveParamsBase,
934                         ctx->above_params_ofs + ctx->above_params_size *(core * 2 + (ctx->AccessUnitNum & 0x1)),
935                         cmdbuf->topaz_above_params);
936
937    RELOC_PIC_PARAMS_PNW(&psPicParams->CodedBase, ctx->coded_buf_per_slice * core, ctx->coded_buf->psb_buffer);
938    drv_debug_msg(VIDEO_DEBUG_GENERAL, "For core %d, above_parmas_off %x\n", core, ctx->above_params_ofs + ctx->above_params_size *(core * 2 + ((ctx->AccessUnitNum) & 0x1)));
939
940   return VA_STATUS_SUCCESS;
941}
942
943static VAStatus pnw_SetupRCParam(context_ENC_p ctx)
944{
945    pnw_cmdbuf_p cmdbuf = ctx->obj_context->pnw_cmdbuf;
946    PIC_PARAMS  *psPicParams = (PIC_PARAMS  *)cmdbuf->pic_params_p;
947    PIC_PARAMS  *psPicParamsTmp;
948    int origin_qp, i;/* in DDK setup_rc will change qp strangly,
949                   * just for keep same with DDK
950                   */
951
952    origin_qp = ctx->sRCParams.InitialQp;
953
954    psPicParams->Flags |= ISRC_FLAGS;
955    pnw__setup_rcdata(ctx, psPicParams, &ctx->sRCParams);
956
957    /* restore it, just keep same with DDK */
958    ctx->sRCParams.InitialQp = origin_qp;
959
960    /* Assume IN_RC_PARAMS for each core is identical, and copy for each */
961    for (i = (ctx->ParallelCores - 1); i > 0; i--) {
962        psPicParamsTmp = (PIC_PARAMS  *)(cmdbuf->pic_params_p + ctx->pic_params_size * i);
963        memcpy((unsigned char *)&psPicParamsTmp->sInParams,
964               (unsigned char *)&psPicParams->sInParams,
965               sizeof(IN_RC_PARAMS));
966        psPicParamsTmp->Flags |= psPicParams->Flags;
967    }
968
969    /* save IN_RC_PARAMS into the cache */
970    memcpy(&ctx->in_params_cache, (unsigned char *)&psPicParams->sInParams, sizeof(IN_RC_PARAMS));
971    return VA_STATUS_SUCCESS;
972}
973
974VAStatus pnw_EndPicture(context_ENC_p ctx)
975{
976    VAStatus vaStatus = VA_STATUS_SUCCESS;
977    unsigned int i;
978    int index;
979    pnw_cmdbuf_p cmdbuf = ctx->obj_context->pnw_cmdbuf;
980    PIC_PARAMS *psPicParams = (PIC_PARAMS *)cmdbuf->pic_params_p;
981    PIC_PARAMS *psPicParamsSlave = NULL;
982    unsigned int val = 0;
983
984    ctx->AccessUnitNum++;
985
986    if (ctx->sRCParams.RCEnable) {
987        if (ctx->raw_frame_count == 0)
988            pnw_SetupRCParam(ctx);
989        else  if (ctx->sRCParams.bBitrateChanged) {
990            /* Toggle the last bit to make sure encoder firmare recalculate the
991               RC params even if the target bitrate isn't changed.*/
992            val = ~(ctx->sRCParams.BitsPerSecond & 0x1);
993            ctx->sRCParams.BitsPerSecond &= ~1;
994            ctx->sRCParams.BitsPerSecond |= (val & 1);
995
996            drv_debug_msg(VIDEO_DEBUG_GENERAL, "bitrate is changed to %d, "
997                    "update the rc data accordingly\n", ctx->sRCParams.BitsPerSecond);
998            pnw__update_rcdata(ctx, psPicParams, &ctx->sRCParams);
999            if (ctx->sRCParams.MinQP)
1000                psPicParams->sInParams.MinQPVal = ctx->sRCParams.MinQP;
1001            memcpy(&ctx->in_params_cache, (unsigned char *)&psPicParams->sInParams, sizeof(IN_RC_PARAMS));
1002            /* Save rate control info in slave core as well */
1003            for (i = 1; i < ctx->ParallelCores; i++) {
1004                psPicParamsSlave = (PIC_PARAMS *)(cmdbuf->pic_params_p + ctx->pic_params_size * i);
1005                memcpy((unsigned char *)&psPicParamsSlave->sInParams,
1006                        (unsigned char *)&psPicParams->sInParams, sizeof(IN_RC_PARAMS));
1007	    }
1008        }
1009    }
1010
1011#if TOPAZ_PIC_PARAMS_VERBOSE
1012    drv_debug_msg(VIDEO_DEBUG_GENERAL, "End Picture for frame %d\n", ctx->raw_frame_count);
1013    drv_debug_msg(VIDEO_DEBUG_GENERAL, "sizeof PIC_PARAMS %d\n", sizeof(PIC_PARAMS));
1014    drv_debug_msg(VIDEO_DEBUG_GENERAL, "sizeof in_params %d\n", sizeof(psPicParams->sInParams));
1015    drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->SrcYBase  0x%08x\n", psPicParams->SrcYBase);
1016    drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->SrcUBase 0x%08x\n", psPicParams->SrcUBase);
1017    drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->SrcVBase 0x%08x\n", psPicParams->SrcVBase);
1018    drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->DstYBase 0x%08x\n", psPicParams->DstYBase);
1019    drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->DstUVBase 0x%08x\n", psPicParams->DstUVBase);
1020    drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->SrcYStride 0x%08x\n", psPicParams->SrcYStride);
1021    drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->SrcUVStride 0x%08x\n", psPicParams->SrcUVStride);
1022    drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->SrcYRowStride 0x%08x\n", psPicParams->SrcYRowStride);
1023    drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->SrcUVRowStride 0x%08x\n", psPicParams->SrcUVRowStride);
1024    drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->DstYStride 0x%08x\n", psPicParams->DstYStride);
1025    drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->DstUVStride 0x%08x\n", psPicParams->DstUVStride);
1026    drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->CodedBase 0x%08x\n", psPicParams->CodedBase);
1027    drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->BelowParamsInBase 0x%08x\n", psPicParams->BelowParamsInBase);
1028    drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->BelowParamsOutBase 0x%08x\n", psPicParams->BelowParamsOutBase);
1029    drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->AboveParamsBase 0x%08x\n", psPicParams->AboveParamsBase);
1030    drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->Width 0x%08x\n", psPicParams->Width);
1031    drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->Height 0x%08x\n", psPicParams->Height);
1032    drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->Flags 0x%08x\n", psPicParams->Flags);
1033    drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->SerachWidth 0x%08x\n", psPicParams->SearchWidth);
1034    drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->SearchHeight 0x%08x\n", psPicParams->SearchHeight);
1035    drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->NumSlices 0x%08x\n", psPicParams->NumSlices);
1036    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->ClockDivBitrate %lld\n", psPicParams->ClockDivBitrate);
1037    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->MaxBufferMultClockDivBitrate %d\n",
1038                             psPicParams->MaxBufferMultClockDivBitrate);
1039    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.SeInitQP %d\n", psPicParams->sInParams.SeInitQP);
1040    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.MinQPVal %d\n", psPicParams->sInParams.MinQPVal);
1041    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.MaxQPVal %d\n", psPicParams->sInParams.MaxQPVal);
1042    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.MBPerRow %d\n", psPicParams->sInParams.MBPerRow);
1043    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.MBPerFrm %d\n", psPicParams->sInParams.MBPerFrm);
1044    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.MBPerBU %d\n", psPicParams->sInParams.MBPerBU);
1045    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.BUPerFrm %d\n", psPicParams->sInParams.BUPerFrm);
1046    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.IntraPeriod %d\n", psPicParams->sInParams.IntraPeriod);
1047    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.BitsPerFrm %d\n", psPicParams->sInParams.BitsPerFrm);
1048    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.BitsPerBU %d\n", psPicParams->sInParams.BitsPerBU);
1049    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.BitsPerMB %d\n", psPicParams->sInParams.BitsPerMB);
1050    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.BitRate %d\n", psPicParams->sInParams.BitRate);
1051    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.BufferSize %d\n", psPicParams->sInParams.BufferSize);
1052    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.InitialLevel %d\n", psPicParams->sInParams.InitialLevel);
1053    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.InitialDelay %d\n", psPicParams->sInParams.InitialDelay);
1054    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.ScaleFactor %d\n", psPicParams->sInParams.ScaleFactor);
1055    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.VCMBitrateMargin %d\n", psPicParams->sInParams.VCMBitrateMargin);
1056    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.HalfFrameRate %d\n", psPicParams->sInParams.HalfFrameRate);
1057    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.FCode %d\n", psPicParams->sInParams.FCode);
1058    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.BitsPerGOP %d\n", psPicParams->sInParams.BitsPerGOP);
1059    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.AvQPVal %d\n", psPicParams->sInParams.AvQPVal);
1060    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.MyInitQP %d\n", psPicParams->sInParams.MyInitQP);
1061    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.ForeceSkipMargin %d\n", psPicParams->sInParams.ForeceSkipMargin);
1062    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.RCScaleFactor %d\n", psPicParams->sInParams.RCScaleFactor);
1063    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.TransferRate %d\n", psPicParams->sInParams.TransferRate);
1064    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.MaxFrameSize %d\n", psPicParams->sInParams.MaxFrameSize);
1065#endif
1066    /* save current settings */
1067    ctx->previous_ref_surface = ctx->ref_surface;
1068    ctx->previous_dest_surface = ctx->dest_surface; /* reconstructed surface */
1069    SET_CODEDBUF_INFO(SLICE_NUM, ctx->coded_buf->codedbuf_aux_info,
1070        ctx->obj_context->slice_count);
1071    SET_CODEDBUF_INFO(NONE_VCL_NUM, ctx->coded_buf->codedbuf_aux_info,
1072        ctx->none_vcl_nal);
1073
1074    for (index = (ctx->ParallelCores - 1); index >= 0; index--) {
1075        pnw_cmdbuf_insert_command_package(ctx->obj_context,
1076                                          index,
1077                                          MTX_CMDID_END_PIC,
1078                                          NULL,
1079                                          0);
1080    }
1081    psb_buffer_unmap(&cmdbuf->pic_params);
1082    psb_buffer_unmap(&cmdbuf->header_mem);
1083    psb_buffer_unmap(&cmdbuf->slice_params);
1084
1085    /* unmap MTX_CURRENT_IN_PARAMS buffer only when it is mapped */
1086    if (cmdbuf->topaz_in_params_I_p != NULL) {
1087        psb_buffer_unmap(cmdbuf->topaz_in_params_I);
1088        cmdbuf->topaz_in_params_I_p = NULL;
1089    }
1090
1091    if (cmdbuf->topaz_in_params_P_p != NULL) {
1092        psb_buffer_unmap(cmdbuf->topaz_in_params_P);
1093        cmdbuf->topaz_in_params_P_p = NULL;
1094    }
1095
1096    if (cmdbuf->topaz_above_params_p != NULL) {
1097        psb_buffer_unmap(cmdbuf->topaz_above_params);
1098        cmdbuf->topaz_above_params_p = NULL;
1099    }
1100
1101    if (cmdbuf->topaz_below_params_p != NULL) {
1102        psb_buffer_unmap(cmdbuf->topaz_below_params);
1103        cmdbuf->topaz_below_params_p = NULL;
1104    }
1105
1106    if (pnw_context_flush_cmdbuf(ctx->obj_context)) {
1107        vaStatus = VA_STATUS_ERROR_UNKNOWN;
1108    }
1109    ctx->raw_frame_count++;
1110    return vaStatus;
1111}
1112
1113static void pnw__setup_busize(context_ENC_p ctx)
1114{
1115    unsigned int old_busize = ctx->sRCParams.BUSize;
1116    int slices = ctx->obj_context->slice_count;
1117
1118    /* it is called at EndPicture, we should now the Slice number */
1119    //ctx->Slices = ctx->obj_context->slice_count;
1120
1121    /* if no BU size is given then pick one ourselves */
1122    if (ctx->sRCParams.BUSize != 0)  { /* application provided BUSize */
1123        IMG_UINT32 MBs, MBsperSlice, MBsLastSlice;
1124        IMG_UINT32 BUs;
1125        IMG_INT32  SliceHeight;
1126        IMG_UINT32 MaxSlicesPerPipe, MaxMBsPerPipe, MaxBUsPerPipe;
1127
1128        MBs     = ctx->Height * ctx->Width / (16 * 16);
1129
1130        SliceHeight     = ctx->Height / slices;
1131        /* SliceHeight += 15; */
1132        SliceHeight &= ~15;
1133
1134        MBsperSlice     = (SliceHeight * ctx->Width) / (16 * 16);
1135        MBsLastSlice    = MBs - (MBsperSlice * (slices - 1));
1136
1137        /* they have given us a basic unit so validate it */
1138        if (ctx->sRCParams.BUSize < 6) {
1139            drv_debug_msg(VIDEO_DEBUG_ERROR, "ERROR: Basic unit size too small, must be greater than 6\n");
1140            ctx->sRCParams.BUSize = 0; /* need repatch */;
1141        }
1142        if (ctx->sRCParams.BUSize > MBsperSlice) {
1143            drv_debug_msg(VIDEO_DEBUG_ERROR, "ERROR: Basic unit size too large, must be less than the number of macroblocks in a slice\n");
1144            ctx->sRCParams.BUSize = 0; /* need repatch */;
1145        }
1146        if (ctx->sRCParams.BUSize > MBsLastSlice) {
1147            drv_debug_msg(VIDEO_DEBUG_ERROR, "ERROR: Basic unit size too large, must be less than number of macroblocks in the last slice\n");
1148            ctx->sRCParams.BUSize = 0; /* need repatch */;
1149        }
1150
1151        if (ctx->sRCParams.BUSize != 0) {
1152            BUs = MBsperSlice / ctx->sRCParams.BUSize;
1153            if ((BUs * ctx->sRCParams.BUSize) != MBsperSlice)   {
1154                drv_debug_msg(VIDEO_DEBUG_ERROR, "ERROR: Basic unit size not an integer divisor of MB's in a slice");
1155                ctx->sRCParams.BUSize = 0; /* need repatch */;
1156            }
1157        }
1158        if (ctx->sRCParams.BUSize != 0) {
1159            BUs = MBsLastSlice / ctx->sRCParams.BUSize;
1160            if ((BUs * ctx->sRCParams.BUSize) != MBsLastSlice)   {
1161                drv_debug_msg(VIDEO_DEBUG_ERROR, "ERROR: Basic unit size not an integer divisor of MB's in a slice");
1162                ctx->sRCParams.BUSize = 0; /* need repatch */;
1163            }
1164        }
1165
1166        if (ctx->sRCParams.BUSize != 0) {
1167            // check if the number of BUs per pipe is greater than 200
1168            MaxSlicesPerPipe = (slices + ctx->ParallelCores - 1) / ctx->ParallelCores;
1169            MaxMBsPerPipe = (MBsperSlice * (MaxSlicesPerPipe - 1)) + MBsLastSlice;
1170            MaxBUsPerPipe = (MaxMBsPerPipe + ctx->sRCParams.BUSize - 1) / ctx->sRCParams.BUSize;
1171            if (MaxBUsPerPipe > 200) {
1172                drv_debug_msg(VIDEO_DEBUG_ERROR, "ERROR: Basic unit size too small. There must be less than 200 basic units per slice");
1173                ctx->sRCParams.BUSize = 0; /* need repatch */;
1174            }
1175        }
1176    }
1177
1178    if (ctx->sRCParams.BUSize == 0)  {
1179        IMG_UINT32 MBs, MBsperSlice, MBsLastSlice;
1180        IMG_UINT32 BUsperSlice, BUsLastSlice;
1181        IMG_UINT32 MaxSlicesPerPipe, MaxMBsPerPipe, MaxBUsPerPipe;
1182        IMG_INT32  SliceHeight;
1183        IMG_UINT32 BUSize = 6;
1184
1185        MBs     = ctx->Height * ctx->Width / (16 * 16);
1186
1187        SliceHeight     = ctx->Height / slices;
1188        /* SliceHeight += 15; */
1189        SliceHeight &= ~15;
1190
1191        MBsperSlice     = (SliceHeight * ctx->Width) / (16 * 16);
1192        MBsLastSlice = MBs - (MBsperSlice * (slices - 1));
1193
1194        /* Check number of BUs to be encoded on one pipe is less than maximum number allowed 200  */
1195        MaxSlicesPerPipe = (slices + ctx->ParallelCores - 1) / ctx->ParallelCores;
1196        MaxMBsPerPipe = (MBsperSlice * (MaxSlicesPerPipe - 1)) + MBsLastSlice;
1197        MaxBUsPerPipe = (MaxMBsPerPipe + BUSize - 1) / BUSize;
1198
1199        while (MaxBUsPerPipe > 200)  {
1200            BUSize++;
1201            MaxBUsPerPipe = (MaxMBsPerPipe + BUSize - 1) / BUSize;
1202        }
1203
1204        /* Check whether there are integeral number of BUs in the slices  */
1205        BUsperSlice = MBsperSlice / BUSize;
1206        BUsLastSlice = MBsLastSlice / BUSize;
1207        while ((BUsperSlice*BUSize != MBsperSlice) ||
1208               (BUsLastSlice*BUSize != MBsLastSlice)) {
1209            BUSize++;
1210            BUsperSlice = MBsperSlice / BUSize;
1211            BUsLastSlice = MBsLastSlice / BUSize;
1212        }
1213
1214        ctx->sRCParams.BUSize = BUSize;
1215    /*
1216        ctx->sRCParams.InitialLevel = (3 * ctx->sRCParams.BufferSize) >> 4;
1217        ctx->sRCParams.InitialDelay = (13 * ctx->sRCParams.BufferSize) >> 4;
1218    */
1219    }
1220
1221    if (ctx->sRCParams.BUSize != old_busize)
1222        drv_debug_msg(VIDEO_DEBUG_GENERAL, "Patched Basic unit to %d (original=%d)\n", ctx->sRCParams.BUSize, old_busize);
1223}
1224
1225
1226static void pnw__update_rcdata(
1227    context_ENC_p psContext,
1228    PIC_PARAMS *psPicParams,
1229    IMG_RC_PARAMS *psRCParams)
1230{
1231    double      L1, L2, L3, L4, L5, L6, flBpp;
1232    IMG_INT16           i16TempQP;
1233    IMG_INT32   i32BufferSizeInFrames = 0;
1234
1235    flBpp = 1.0 * psRCParams->BitsPerSecond
1236            / (psRCParams->FrameRate * psContext->Width * psContext->Height);
1237
1238    if (psContext->Width <= 176) {
1239        /* for very small franes we need to adjust the calculations */
1240        flBpp = flBpp / 2.0;
1241    }
1242
1243    psPicParams->sInParams.IntraPeriod =  psRCParams->IntraFreq;
1244    psPicParams->sInParams.BitRate = psRCParams->BitsPerSecond;
1245    psPicParams->sInParams.BitsPerFrm = (psRCParams->BitsPerSecond + psRCParams->FrameRate / 2) / psRCParams->FrameRate;
1246    psPicParams->sInParams.BitsPerGOP = (psRCParams->BitsPerSecond / psRCParams->FrameRate) * psRCParams->IntraFreq;
1247    psPicParams->sInParams.BitsPerBU    = psPicParams->sInParams.BitsPerFrm / (4 * psPicParams->sInParams.BUPerFrm);
1248    psPicParams->sInParams.BitsPerMB    = psPicParams->sInParams.BitsPerBU / psRCParams->BUSize;
1249    psPicParams->sInParams.TransferRate = psRCParams->BitsPerSecond / psRCParams->FrameRate;
1250
1251    i32BufferSizeInFrames = psRCParams->BufferSize / psPicParams->sInParams.BitsPerFrm;
1252
1253    /* select thresholds and initial Qps etc that are codec dependent */
1254    switch (psContext->eCodec) {
1255    case IMG_CODEC_H264_CBR:
1256    case IMG_CODEC_H264_VCM:
1257    case IMG_CODEC_H264_VBR:
1258        L1 = 0.1;
1259        L2 = 0.15;
1260        L3 = 0.2;
1261
1262        /* Set MaxQP to avoid blocky image in low bitrate */
1263        /* RCScaleFactor indicates the size of GOP for rate control */
1264        if (psContext->eCodec == IMG_CODEC_H264_VCM) {
1265            psPicParams->sInParams.MaxQPVal = 51;
1266            psPicParams->sInParams.RCScaleFactor = 16;
1267        }
1268        else {
1269            psPicParams->sInParams.MaxQPVal = 51;
1270            psPicParams->sInParams.RCScaleFactor = 16;
1271        }
1272
1273        /* Setup MAX and MIN Quant Values */
1274        if (flBpp >= 0.50)
1275            i16TempQP = 4;
1276        else
1277            i16TempQP = (unsigned int)(26 - (40 * flBpp));
1278
1279        psPicParams->sInParams.MinQPVal = (max(min(psPicParams->sInParams.MaxQPVal, i16TempQP), 0));
1280
1281        L1 = 0.050568;
1282        L2 = 0.202272;
1283        L3 = 0.40454321;
1284        L4 = 0.80908642;
1285        L5 = 1.011358025;
1286        if (flBpp < L1)
1287            psPicParams->sInParams.SeInitQP = (IMG_UINT8)(47 - 78.10 * flBpp);
1288
1289        else if (flBpp >= L1 && flBpp < L2)
1290            psPicParams->sInParams.SeInitQP = (IMG_UINT8)(45 - 66.67 * flBpp);
1291
1292        else if (flBpp >= L2 && flBpp < L3)
1293            psPicParams->sInParams.SeInitQP = (IMG_UINT8)(36 - 24.72 * flBpp);
1294
1295        else if (flBpp >= L3 && flBpp < L4)
1296            psPicParams->sInParams.SeInitQP = (IMG_UINT8)(34 - 19.78 * flBpp);
1297
1298        else if (flBpp >= L4 && flBpp < L5)
1299            psPicParams->sInParams.SeInitQP = (IMG_UINT8)(27 - 9.89 * flBpp);
1300
1301        else if (flBpp >= L5 && flBpp < 4)
1302            psPicParams->sInParams.SeInitQP = (IMG_UINT8)(20 - 4.95 * flBpp);
1303        else
1304            psPicParams->sInParams.SeInitQP = psPicParams->sInParams.MinQPVal;
1305
1306        if (psPicParams->sInParams.SeInitQP < psPicParams->sInParams.MinQPVal)
1307            psPicParams->sInParams.SeInitQP = psPicParams->sInParams.MinQPVal;
1308
1309        break;
1310
1311    case IMG_CODEC_MPEG4_CBR:
1312    case IMG_CODEC_MPEG4_VBR:
1313    case IMG_CODEC_H263_CBR:
1314    case IMG_CODEC_H263_VBR:
1315        psPicParams->sInParams.RCScaleFactor = 16;
1316        psPicParams->sInParams.MaxQPVal  = 31;
1317
1318        if (psContext->Width <= 176) {
1319            L1 = 0.043;
1320            L2 = 0.085;
1321            L3 = 0.126;
1322            L4 = 0.168;
1323            L5 = 0.336;
1324            L6 = 0.505;
1325        } else if (psContext->Width == 352) {
1326            L1 = 0.065;
1327            L2 = 0.085;
1328            L3 = 0.106;
1329            L4 = 0.126;
1330            L5 = 0.168 ;
1331            L6 = 0.210;
1332        } else {
1333            L1 = 0.051;
1334            L2 = 0.0770;
1335            L3 = 0.096;
1336            L4 = 0.145;
1337            L5 = 0.193;
1338            L6 = 0.289;
1339        }
1340
1341        /* Calculate Initial QP if it has not been specified */
1342        if (flBpp < L1)
1343            psPicParams->sInParams.SeInitQP = 31;
1344
1345        else if (flBpp >= L1 && flBpp < L2)
1346            psPicParams->sInParams.SeInitQP = 26;
1347
1348        else if (flBpp >= L2 && flBpp < L3)
1349            psPicParams->sInParams.SeInitQP = 22;
1350
1351        else if (flBpp >= L3 && flBpp < L4)
1352            psPicParams->sInParams.SeInitQP = 18;
1353
1354        else if (flBpp >= L4 && flBpp < L5)
1355            psPicParams->sInParams.SeInitQP = 14;
1356
1357        else if (flBpp >= L5 && flBpp < L6)
1358            psPicParams->sInParams.SeInitQP = 10;
1359        else
1360            psPicParams->sInParams.SeInitQP = 8;
1361
1362        psPicParams->sInParams.AvQPVal =  psPicParams->sInParams.SeInitQP;
1363
1364        if (flBpp >= 0.25
1365                && (psContext->eCodec == IMG_CODEC_MPEG4_CBR ||
1366                    psContext->eCodec == IMG_CODEC_MPEG4_VBR)) {
1367            psPicParams->sInParams.MinQPVal = 1;
1368        } else {
1369            psPicParams->sInParams.MinQPVal = 4;
1370        }
1371        break;
1372
1373    default:
1374        /* the NO RC cases will fall here */
1375        break;
1376    }
1377
1378    /* Set up Input Parameters that are mode dependent */
1379    switch (psContext->eCodec) {
1380    case IMG_CODEC_H264_NO_RC:
1381    case IMG_CODEC_H263_NO_RC:
1382    case IMG_CODEC_MPEG4_NO_RC:
1383        return ;
1384
1385    case IMG_CODEC_H264_VCM:
1386        psPicParams->Flags      |= (ISVCM_FLAGS | ISCBR_FLAGS);
1387        if (psContext->Height >= 480) {
1388            /* for SD and above we can target 95% (122/128) of maximum bitrate */
1389            psPicParams->sInParams.VCMBitrateMargin = 122;
1390        } else {
1391            /* for less and SD we target 99% of maximum bitrate */
1392            psPicParams->sInParams.VCMBitrateMargin = 127;
1393        }
1394        if (i32BufferSizeInFrames < 15) {
1395            /* when we have a very small window size we reduce the target
1396             * further to avoid too much skipping */
1397            psPicParams->sInParams.VCMBitrateMargin -= 5;
1398        }
1399        psPicParams->sInParams.ForeceSkipMargin = 0; /* start skipping MBs when within 500 bits of slice or frame limit */
1400        if (psRCParams->BitsPerSecond < 1000000) {      // 1 Mbits/s
1401            psPicParams->sInParams.ScaleFactor = 0;
1402        } else if (psRCParams->BitsPerSecond < 2000000) { // 2 Mbits/s
1403            psPicParams->sInParams.ScaleFactor = 1;
1404        } else if (psRCParams->BitsPerSecond < 4000000) { // 4 Mbits/s
1405            psPicParams->sInParams.ScaleFactor = 2;
1406        } else if (psRCParams->BitsPerSecond < 8000000) { // 8 Mbits/s
1407            psPicParams->sInParams.ScaleFactor = 3;
1408        } else {
1409            psPicParams->sInParams.ScaleFactor = 4;
1410        }
1411
1412        psPicParams->sInParams.BufferSize = i32BufferSizeInFrames;
1413
1414        break;
1415    case IMG_CODEC_H264_CBR:
1416        psPicParams->Flags |= ISCBR_FLAGS;
1417        /* ------------------- H264 CBR RC ------------------- */
1418        /* Initialize the parameters of fluid flow traffic model. */
1419        psPicParams->sInParams.BufferSize = psRCParams->BufferSize;
1420
1421        /* HRD consideration - These values are used by H.264 reference code. */
1422        if (psRCParams->BitsPerSecond < 1000000) {      /* 1 Mbits/s */
1423            psPicParams->sInParams.ScaleFactor = 0;
1424        } else if (psRCParams->BitsPerSecond < 2000000) { /* 2 Mbits/s */
1425            psPicParams->sInParams.ScaleFactor = 1;
1426        } else if (psRCParams->BitsPerSecond < 4000000) { /* 4 Mbits/s */
1427            psPicParams->sInParams.ScaleFactor = 2;
1428        } else if (psRCParams->BitsPerSecond < 8000000) { /* 8 Mbits/s */
1429            psPicParams->sInParams.ScaleFactor = 3;
1430        } else {
1431            psPicParams->sInParams.ScaleFactor = 4;
1432        }
1433        break;
1434
1435    case IMG_CODEC_MPEG4_CBR:
1436    case IMG_CODEC_H263_CBR:
1437        psPicParams->Flags |= ISCBR_FLAGS;
1438
1439        flBpp  = 256 * (psRCParams->BitsPerSecond / psContext->Width);
1440        flBpp /= (psContext->Height * psRCParams->FrameRate);
1441
1442        if ((psPicParams->sInParams.MBPerFrm > 1024 && flBpp < 16) || (psPicParams->sInParams.MBPerFrm <= 1024 && flBpp < 24))
1443            psPicParams->sInParams.HalfFrameRate = 1;
1444        else
1445            psPicParams->sInParams.HalfFrameRate = 0;
1446
1447        if (psPicParams->sInParams.HalfFrameRate >= 1) {
1448            psPicParams->sInParams.SeInitQP = 31;
1449            psPicParams->sInParams.AvQPVal = 31;
1450            psPicParams->sInParams.MyInitQP = 31;
1451        }
1452
1453        psPicParams->sInParams.BufferSize = psRCParams->BufferSize;
1454        if (psPicParams->sInParams.BufferSize > 112 * 16384) // Simple Profile L5 Constraints
1455            psPicParams->sInParams.BufferSize = 112 * 16384;
1456        break;
1457
1458    case IMG_CODEC_MPEG4_VBR:
1459    case IMG_CODEC_H263_VBR:
1460    case IMG_CODEC_H264_VBR:
1461        psPicParams->Flags |= ISVBR_FLAGS;
1462
1463        psPicParams->sInParams.MBPerBU  = psPicParams->sInParams.MBPerFrm;
1464        psPicParams->sInParams.BUPerFrm = 1;
1465
1466        /* Initialize the parameters of fluid flow traffic model. */
1467        psPicParams->sInParams.BufferSize = psRCParams->BufferSize;
1468
1469        if (psContext->eCodec != IMG_CODEC_H264_VBR) {
1470            if (psPicParams->sInParams.BufferSize >  112 * 16384)
1471                psPicParams->sInParams.BufferSize = 112 * 16384; // Simple Profile L5 Constraints
1472        }
1473
1474        /* These scale factor are used only for rate control to avoid overflow */
1475        /* in fixed-point calculation these scale factors are decided by bit rate */
1476        if (psRCParams->BitsPerSecond < 640000) {
1477            psPicParams->sInParams.ScaleFactor  = 2;                                            /* related to complexity */
1478        } else if (psRCParams->BitsPerSecond < 2000000) {
1479            psPicParams->sInParams.ScaleFactor  = 4;
1480        } else {
1481            psPicParams->sInParams.ScaleFactor  = 6;
1482        }
1483        break;
1484    default:
1485        break;
1486    }
1487
1488    psPicParams->sInParams.MyInitQP     = psPicParams->sInParams.SeInitQP;
1489
1490#if 0
1491    if (psContext->SyncSequencer)
1492        psPicParams->Flags |= SYNC_SEQUENCER;
1493#endif
1494
1495    psPicParams->sInParams.InitialDelay = psRCParams->InitialDelay;
1496    psPicParams->sInParams.InitialLevel = psRCParams->InitialLevel;
1497    psRCParams->InitialQp = psPicParams->sInParams.SeInitQP;
1498
1499    drv_debug_msg(VIDEO_DEBUG_GENERAL, "InitQP %d, minQP %d, maxQP %d\n",
1500            psPicParams->sInParams.SeInitQP,
1501            psPicParams->sInParams.MinQPVal,
1502            psPicParams->sInParams.MaxQPVal);
1503
1504    /* The rate control uses this value to adjust the reaction rate
1505       to larger than expected frames in long GOPS*/
1506
1507    return;
1508}
1509
1510
1511/***********************************************************************************
1512 * Function Name      : SetupRCData
1513 * Inputs             :
1514 * Outputs            :
1515 * Returns            :
1516 * Description        : Sets up RC Data
1517 ************************************************************************************/
1518void pnw__setup_rcdata(
1519    context_ENC_p psContext,
1520    PIC_PARAMS *psPicParams,
1521    IMG_RC_PARAMS *psRCParams)
1522{
1523    IMG_UINT8   ui8InitialSeInitQP;
1524
1525    /* frameskip is always cleared, specially handled at vaEndPicture */
1526    psRCParams->FrameSkip = 0;
1527
1528    if (!psRCParams->BitsPerSecond)
1529        psRCParams->BitsPerSecond = 64000;
1530    /*
1531        if (psRCParams->BitsPerSecond > max_bitrate)
1532            psRCParams->BitsPerSecond = max_bitrate;
1533    */
1534    if (!psRCParams->FrameRate)
1535        psRCParams->FrameRate = 30;
1536
1537    pnw__setup_busize(psContext); /* calculate BasicUnitSize */
1538
1539    psPicParams->sInParams.SeInitQP = psRCParams->InitialQp;
1540
1541    psPicParams->sInParams.MBPerRow = (psContext->Width >> 4);
1542    psPicParams->sInParams.MBPerBU = psRCParams->BUSize;
1543    psPicParams->sInParams.MBPerFrm     = (psContext->Width >> 4) * (psContext->Height >> 4);
1544    psPicParams->sInParams.BUPerFrm     = (psPicParams->sInParams.MBPerFrm) / psRCParams->BUSize;
1545    psPicParams->sInParams.AvQPVal = psRCParams->InitialQp;
1546    psPicParams->sInParams.MyInitQP     = psRCParams->InitialQp;
1547    psPicParams->sInParams.MaxFrameSize = psRCParams->BitsPerSecond / psRCParams->FrameRate;
1548
1549    ui8InitialSeInitQP = psPicParams->sInParams.SeInitQP;
1550
1551    pnw__update_rcdata(psContext, psPicParams, psRCParams);
1552
1553    /*If MinQP has been set, restore this value rather than
1554     *the calculated value set by UpdateRCData()*/
1555    if (psRCParams->MinQP) {
1556        psPicParams->sInParams.MinQPVal = (IMG_UINT8)psRCParams->MinQP;
1557    }
1558
1559    /*If SeInitQP has been set, restore this value and other
1560     * dependant variables rather than the calculated values set by UpdateRCData()*/
1561    if (ui8InitialSeInitQP) {
1562        psPicParams->sInParams.SeInitQP = ui8InitialSeInitQP;
1563        psPicParams->sInParams.MyInitQP = ui8InitialSeInitQP;
1564        psRCParams->InitialQp = ui8InitialSeInitQP;
1565    }
1566
1567    /* HRD parameters are meaningless without a bitrate
1568     * HRD parameters are not supported in VCM mode */
1569    if (psRCParams->BitsPerSecond == 0 || psContext->eCodec == IMG_CODEC_H264_VCM)
1570         psContext->bInserHRDParams = IMG_FALSE;
1571
1572    if (psContext->bInserHRDParams) {
1573        psPicParams->ClockDivBitrate = (90000 * 0x100000000LL);
1574        psPicParams->ClockDivBitrate /= psRCParams->BitsPerSecond;
1575        psPicParams->MaxBufferMultClockDivBitrate = (IMG_UINT32)
1576                (((IMG_UINT64)(psRCParams->BufferSize) * (IMG_UINT64) 90000)
1577                 / (IMG_UINT64) psRCParams->BitsPerSecond);
1578    }
1579    return ;
1580}
1581
1582static void pnw__setup_qpvalue_h264(
1583    MTX_CURRENT_IN_PARAMS * psCurrent,
1584    IMG_BYTE bySliceQP)
1585{
1586    /* H.264 QP scaling tables */
1587    IMG_BYTE HOST_PVR_QP_SCALE_CR[52] = {
1588        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
1589        12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
1590        28, 29, 29, 30, 31, 32, 32, 33, 34, 34, 35, 35, 36, 36, 37, 37,
1591        37, 38, 38, 38, 39, 39, 39, 39
1592    };
1593
1594    psCurrent->bySliceQP = bySliceQP;
1595    psCurrent->bySliceQPC = HOST_PVR_QP_SCALE_CR[psCurrent->bySliceQP];
1596}
1597
1598
1599static void pnw__setup_qpvalues_mpeg4(
1600    MTX_CURRENT_IN_PARAMS * psCurrent,
1601    IMG_BYTE bySliceQP)
1602{
1603    psCurrent->bySliceQP =      bySliceQP;
1604}
1605
1606static void pnw__setup_slice_row_params(
1607    context_ENC_p ctx,
1608    IMG_BOOL IsIntra,
1609    IMG_UINT16 CurrentRowY,
1610    IMG_INT16 SliceStartRowY,
1611    IMG_INT16 SliceHeight,
1612    IMG_BOOL VectorsValid,
1613    int bySliceQP)
1614{
1615    /* Note: CurrentRowY and SliceStartRowY are now in pixels (not MacroBlocks)
1616     * - saves needless multiplications and divisions
1617     */
1618    MTX_CURRENT_IN_PARAMS *psCurrent;
1619    pnw_cmdbuf_p cmdbuf = ctx->obj_context->pnw_cmdbuf;
1620
1621    IMG_INT16   iPos, iYPos, srcY;
1622    IMG_UINT16  ui16tmp;
1623    IMG_UINT16 ui16SearchWidth, ui16SearchHeight, ui16SearchLeftOffset, ui16SearchTopOffset, ui16CurBlockX;
1624
1625    if (IsIntra && cmdbuf->topaz_in_params_I_p == NULL) {
1626        VAStatus vaStatus = psb_buffer_map(cmdbuf->topaz_in_params_I, &cmdbuf->topaz_in_params_I_p);
1627        if (vaStatus != VA_STATUS_SUCCESS) {
1628            drv_debug_msg(VIDEO_DEBUG_ERROR, "map topaz MTX_CURRENT_IN_PARAMS failed\n");
1629            return;
1630        }
1631    }
1632
1633    if ((!IsIntra) && cmdbuf->topaz_in_params_P_p == NULL) {
1634        VAStatus vaStatus = psb_buffer_map(cmdbuf->topaz_in_params_P, &cmdbuf->topaz_in_params_P_p);
1635        if (vaStatus != VA_STATUS_SUCCESS) {
1636            drv_debug_msg(VIDEO_DEBUG_ERROR, "map topaz MTX_CURRENT_IN_PARAMS failed\n");
1637            return;
1638        }
1639    }
1640
1641    if (IsIntra)
1642        psCurrent = (MTX_CURRENT_IN_PARAMS*)(cmdbuf->topaz_in_params_I_p + ctx->in_params_ofs);
1643    else
1644        psCurrent = (MTX_CURRENT_IN_PARAMS*)(cmdbuf->topaz_in_params_P_p + ctx->in_params_ofs);
1645
1646    psCurrent += (CurrentRowY  * (ctx->Width) / 256);
1647
1648    // Note: CurrentRowY and iSliceStartRowY are now in pixels (not MacroBlocks) - saves needless multiplications and divisions
1649
1650    ui16SearchHeight = min(MVEA_LRB_SEARCH_HEIGHT, ctx->Height);
1651    ui16SearchWidth = min(MVEA_LRB_SEARCH_WIDTH, ctx->Width);
1652    ui16SearchLeftOffset = (((ui16SearchWidth / 2) / 16) * 16); // this is the amount of data that gets preloaded
1653    ui16SearchTopOffset = (((ui16SearchHeight / 2) / 16) * 16);
1654    ui16CurBlockX = MVEA_LRB_SEARCH_WIDTH - (ui16SearchLeftOffset + 16); // this is our block position relative to the start of the LRB
1655
1656    if ((iYPos = srcY = CurrentRowY - ui16SearchTopOffset) < 0)
1657        srcY = 0;
1658    else if (iYPos > ctx->HeightMinusLRB_TopAndBottom_OffsetsPlus16)
1659        srcY = ctx->HeightMinusLRBSearchHeight;
1660
1661
1662    /*DDK 243 removed this block of code.*/
1663    /*if((ctx->eCodec==IMG_CODEC_H263_NO_RC)||(ctx->eCodec==IMG_CODEC_H263_CBR)||(ctx->eCodec==IMG_CODEC_H263_VBR))
1664      ui16tmp = CurrentRowY;
1665      else*/
1666    ui16tmp = (CurrentRowY != SliceStartRowY);
1667
1668    for (iPos = 0; iPos < ctx->Width; iPos += 16, psCurrent++) {
1669        memset(psCurrent, 0, sizeof(MTX_CURRENT_IN_PARAMS));
1670        psCurrent->MVValid = 0;
1671        psCurrent->ParamsValid = 0;
1672
1673        if (SliceStartRowY) {
1674            psCurrent->MVValid = VECTORS_ABOVE_VALID;
1675        }
1676        /* Setup the parameters and motion vectors*/
1677        if (ui16tmp) {
1678            psCurrent->MVValid = VECTORS_ABOVE_VALID | DO_INTRA_PRED;
1679            psCurrent->ParamsValid |= PARAMS_ABOVE_VALID;
1680
1681            if (iPos + 16 < ctx->Width) {
1682                psCurrent->ParamsValid |= PARAMS_ABOVER_VALID;
1683                psCurrent->MVValid |= /*VECTORS_LEFT_VALID; //*/(1 << 2); /* Vectors left valid define looks wrong*/
1684            }
1685
1686            if (iPos > 0 && (iPos < ctx->Width)) {
1687                psCurrent->ParamsValid |= PARAMS_ABOVEL_VALID;
1688                psCurrent->MVValid |= VECTORS_ABOVE_LEFT_VALID; //(1<<0)
1689            }
1690        } else {
1691            // are we the first MB in a new slice?
1692            if (iPos == 0) {
1693                if ((ctx->eCodec == IMG_CODEC_H263_NO_RC) || (ctx->eCodec == IMG_CODEC_H263_CBR) || (ctx->eCodec == IMG_CODEC_H263_VBR)) {
1694                    if (iYPos == -ui16SearchTopOffset)
1695                        psCurrent->ParamsValid |= MB_START_OF_SLICE;// OPTI?
1696                } else {
1697                    psCurrent->ParamsValid |= MB_START_OF_SLICE;// OPTI?
1698                }
1699            }
1700        }
1701        /*DDK 243 removed this block of code.*/
1702        /*if((ctx->eCodec==IMG_CODEC_H263_NO_RC) || (ctx->eCodec==IMG_CODEC_H263_CBR)||(ctx->eCodec==IMG_CODEC_H263_VBR))
1703          {
1704        // clear the above params valid bits
1705        psCurrent->ParamsValid &=~(PARAMS_ABOVEL_VALID|PARAMS_ABOVER_VALID|PARAMS_ABOVE_VALID); // OPTI
1706        }*/
1707        // Have to fill in the right hand row of 4x4 vectors into the the left block
1708        if (iPos) {
1709            psCurrent->MVValid |= DO_INTRA_PRED | (1 << 3); /*MV_VALID define looks wrong?! so use hard coded value for now*/
1710            psCurrent->ParamsValid |= 8; //(1<<3)
1711        }
1712        if (iPos == ctx->Width - 16) {
1713            // indicate the last MB in a row
1714            psCurrent->ParamsValid |= MB_END_OF_ROW;
1715            // are we the last mb in the slice?
1716            if (iYPos == (SliceStartRowY + SliceHeight - (ui16SearchTopOffset + 16))) {
1717                psCurrent->ParamsValid |= MB_END_OF_SLICE;
1718                if (iYPos == ctx->HeightMinus16MinusLRBTopOffset) {
1719                    psCurrent->ParamsValid |= MB_END_OF_PICTURE;
1720                }
1721            }
1722        }
1723        // And now the below block
1724        // should do some kind of check to see if we are the first inter block, as otherwise the vectors will be invalid!
1725        if (VectorsValid) {
1726            if (iYPos < ctx->HeightMinus16MinusLRBTopOffset) {
1727                psCurrent->MVValid |= VECTORS_BELOW_VALID; //(1<<4)
1728
1729                if (iYPos < ctx->HeightMinus32MinusLRBTopOffset) {
1730                    psCurrent->MVValid |= VECTORS_2BELOW_VALID; //(1<<5)
1731                }
1732            }
1733        }
1734
1735        /*Set up IPEMin and Max for coordinate X in the search reference region*/
1736        /*And set up flags in SPEMax when needed*/
1737        if (iPos <= ui16SearchLeftOffset) {
1738            psCurrent->IPEMin[0] = ui16CurBlockX - iPos;
1739            psCurrent->RealEdge |= SPE_EDGE_LEFT;
1740        } else {
1741            psCurrent->IPEMin[0] = ui16CurBlockX / 16;
1742        }
1743
1744        if ((iPos + ui16SearchLeftOffset + 16) > ctx->Width) {
1745            psCurrent->IPEMax[0] = (ui16CurBlockX - 1 + ctx->Width) - iPos; //(112 - 1) - ((iPos + 48+16) - ctx->psVideo->ui16Width);
1746            psCurrent->RealEdge |= SPE_EDGE_RIGHT;
1747        } else {
1748            psCurrent->IPEMax[0] = (ui16CurBlockX + 16 + ui16SearchLeftOffset) - 1 - 3; //(112 - 1) - 3;
1749        }
1750
1751        /*Set up IPEMin and Max for Y coordinate in the search reference region*/
1752        /*And set up flags in SPEMax when needed*/
1753        if (iYPos <= 0) {
1754            psCurrent->IPEMin[1] = 0;
1755            psCurrent->RealEdge |= SPE_EDGE_TOP;
1756        } else {
1757            psCurrent->IPEMin[1] = 3;
1758        }
1759
1760        //Max Y
1761        if (iYPos > ctx->HeightMinusLRB_TopAndBottom_OffsetsPlus16) {
1762            psCurrent->IPEMax[1] = ui16SearchHeight - 1;
1763            psCurrent->RealEdge |= ui16SearchHeight - 4;
1764        } else {
1765            psCurrent->IPEMax[1] = ui16SearchHeight - 4;
1766        }
1767
1768        psCurrent->CurBlockAddr = ((ui16CurBlockX) / 16);
1769        psCurrent->CurBlockAddr |= ((IMG_UINT8)(((iYPos + ui16SearchTopOffset) - srcY) / 16) << 4);
1770
1771        /* Setup the control register values
1772           These will get setup and transferred to a different location within the macroblock parameter structure.
1773           They are then read out of the esb by the mtx and used to control the hardware units
1774           */
1775        psCurrent->IPEControl = ctx->IPEControl;
1776
1777        switch (ctx->eCodec) {
1778        case IMG_CODEC_H263_NO_RC:
1779        case IMG_CODEC_H263_VBR:
1780        case IMG_CODEC_H263_CBR:
1781            pnw__setup_qpvalues_mpeg4(psCurrent, bySliceQP);
1782            psCurrent->JMCompControl = F_ENCODE(2, MVEA_CR_JMCOMP_MODE);
1783            psCurrent->VLCControl = F_ENCODE(3, TOPAZ_VLC_CR_CODEC) | F_ENCODE(IsIntra ? 0 : 1, TOPAZ_VLC_CR_SLICE_CODING_TYPE);
1784            break;
1785        case IMG_CODEC_MPEG4_NO_RC:
1786        case IMG_CODEC_MPEG4_VBR:
1787        case IMG_CODEC_MPEG4_CBR:
1788            pnw__setup_qpvalues_mpeg4(psCurrent, bySliceQP);
1789            psCurrent->JMCompControl = F_ENCODE(1, MVEA_CR_JMCOMP_MODE) | F_ENCODE(1, MVEA_CR_JMCOMP_AC_ENABLE);
1790            psCurrent->VLCControl = F_ENCODE(2, TOPAZ_VLC_CR_CODEC) | F_ENCODE(IsIntra ? 0 : 1, TOPAZ_VLC_CR_SLICE_CODING_TYPE);
1791            break;
1792        default:
1793        case IMG_CODEC_H264_NO_RC:
1794        case IMG_CODEC_H264_VBR:
1795        case IMG_CODEC_H264_CBR:
1796        case IMG_CODEC_H264_VCM:
1797            pnw__setup_qpvalue_h264(psCurrent, bySliceQP);
1798            psCurrent->JMCompControl = F_ENCODE(0, MVEA_CR_JMCOMP_MODE);
1799            psCurrent->VLCControl = F_ENCODE(1, TOPAZ_VLC_CR_CODEC) | F_ENCODE(IsIntra ? 0 : 1, TOPAZ_VLC_CR_SLICE_CODING_TYPE);
1800            break;
1801        }
1802    }
1803
1804    // now setup the dummy end of frame macroblock.
1805    if ((CurrentRowY + 16) >= ctx->Height) {
1806        memset(psCurrent, 0, sizeof(MTX_CURRENT_IN_PARAMS));
1807        psCurrent->MVValid = DO_INTRA_PRED;
1808        psCurrent->ParamsValid = 0;
1809        psCurrent->RealEdge = 0;
1810    }
1811}
1812
1813void pnw_setup_slice_params(
1814    context_ENC_p  ctx,
1815    IMG_UINT16 YSliceStartPos,
1816    IMG_UINT16 SliceHeight,
1817    IMG_BOOL IsIntra,
1818    IMG_BOOL  VectorsValid,
1819    int bySliceQP)
1820{
1821    IMG_UINT16 Rows, CurrentRowY;
1822
1823    Rows = SliceHeight / 16;
1824    CurrentRowY = YSliceStartPos;
1825
1826    while (Rows) {
1827        pnw__setup_slice_row_params(
1828            ctx,
1829            IsIntra,
1830            CurrentRowY,
1831            YSliceStartPos,
1832            SliceHeight,
1833            VectorsValid, bySliceQP);
1834
1835        CurrentRowY += 16;
1836        Rows--;
1837    }
1838
1839}
1840
1841
1842
1843IMG_UINT32 pnw__send_encode_slice_params(
1844    context_ENC_p ctx,
1845    IMG_BOOL IsIntra,
1846    IMG_UINT16 CurrentRow,
1847    IMG_UINT8  DeblockIDC,
1848    IMG_UINT32 FrameNum,
1849    IMG_UINT16 SliceHeight,
1850    IMG_UINT16 CurrentSlice)
1851{
1852    SLICE_PARAMS *psSliceParams;
1853    IMG_INT16 RowOffset;
1854    IMG_UINT16 SearchHeight, SearchTopOffset;
1855
1856    psb_buffer_p psCoded;
1857    object_surface_p ref_surface;
1858    psb_buffer_p psRef;
1859    pnw_cmdbuf_p cmdbuf = ctx->obj_context->pnw_cmdbuf;
1860
1861
1862    drv_debug_msg(VIDEO_DEBUG_GENERAL, "Send encode slice parmas, Is Intra:%d, CurrentRow:%d" \
1863                             "DeblockIDC:%d, FrameNum:%d, SliceHeight:%d, CurrentSlice:%d\n",
1864                             IsIntra, CurrentRow, DeblockIDC, FrameNum, SliceHeight, CurrentSlice);
1865
1866    ref_surface = ctx->ref_surface;
1867    psRef = &ctx->ref_surface->psb_surface->buf;
1868    psCoded = ctx->coded_buf->psb_buffer;
1869
1870    psSliceParams = (SLICE_PARAMS *)(cmdbuf->slice_params_p +
1871                                     CurrentSlice * ((sizeof(SLICE_PARAMS) + 15) & 0xfff0));
1872
1873    psSliceParams->SliceHeight = SliceHeight;
1874    psSliceParams->SliceStartRowNum = CurrentRow / 16;
1875    psSliceParams->ScanningIntraParams = (1 << SCANNING_INTRA_WIDTH_SHIFT) |
1876        (1 << SCANNING_INTRA_STEP_SHIFT);
1877
1878    /* We want multiple ones of these so we can submit multiple slices without having to wait for the next */
1879    psSliceParams->Flags = 0;
1880    psSliceParams->HostCtx = 0xdafed123;
1881
1882#ifdef VA_EMULATOR
1883    psSliceParams->RefYStride = ref_surface->psb_surface->stride;
1884    psSliceParams->RefUVStride = ref_surface->psb_surface->stride;
1885    psSliceParams->RefYRowStride =  ref_surface->psb_surface->stride * 16;
1886    psSliceParams->RefUVRowStride = ref_surface->psb_surface->stride * 16 / 2;
1887#else
1888    psSliceParams->RefYStride = ref_surface->psb_surface->stride;
1889    psSliceParams->RefUVStride = ref_surface->psb_surface->stride;
1890    psSliceParams->RefYRowStride =  ref_surface->psb_surface->stride * 16;
1891    psSliceParams->RefUVRowStride = ref_surface->psb_surface->stride * 16 / 2;
1892#endif
1893    psSliceParams->NumAirMBs = ctx->num_air_mbs;
1894    psSliceParams->AirThreshold = ctx->air_threshold;
1895
1896    if (ctx->eCodec == IMG_CODEC_H264_VCM && ctx->max_slice_size == 0)
1897        psSliceParams->MaxSliceSize = ctx->Width * ctx->Height * 12 / 2;
1898    else
1899        psSliceParams->MaxSliceSize = ctx->max_slice_size;
1900    psSliceParams->FCode = ctx->FCode;/* Not clear yet, This field is not appare in firmware doc */
1901
1902    SearchHeight = min(MVEA_LRB_SEARCH_HEIGHT, ctx->Height);
1903    SearchTopOffset = (((SearchHeight / 2) / 16) * 16);
1904
1905    RowOffset = CurrentRow - SearchTopOffset;
1906    if (RowOffset <= 0)
1907        RowOffset = 0;
1908    if (RowOffset > (ctx->Height - SearchHeight))
1909        RowOffset = (ctx->Height - SearchHeight);
1910    if (!IsIntra) {
1911        psSliceParams->Flags |= ISINTER_FLAGS;
1912    }
1913
1914    switch (DeblockIDC) {
1915    case 0:
1916        psSliceParams->Flags |= DEBLOCK_FRAME;
1917        break;
1918    case 2:
1919        psSliceParams->Flags |= DEBLOCK_SLICE;
1920        break;
1921    case 1:
1922    default:
1923        // do nothing
1924        break;
1925    }
1926
1927    switch (ctx->eCodec) {
1928    case IMG_CODEC_H263_NO_RC:
1929    case IMG_CODEC_H263_VBR:
1930    case IMG_CODEC_H263_CBR:
1931        psSliceParams->Flags |= ISH263_FLAGS;
1932        break;
1933    case IMG_CODEC_MPEG4_NO_RC:
1934    case IMG_CODEC_MPEG4_VBR:
1935    case IMG_CODEC_MPEG4_CBR:
1936        psSliceParams->Flags |= ISMPEG4_FLAGS;
1937        break;
1938    case IMG_CODEC_H264_NO_RC:
1939    case IMG_CODEC_H264_CBR:
1940    case IMG_CODEC_H264_VCM:
1941    case IMG_CODEC_H264_VBR:
1942        psSliceParams->Flags |= ISH264_FLAGS;
1943        break;
1944    default:
1945        psSliceParams->Flags |= ISH264_FLAGS;
1946        printf("No format specified defaulting to h.264\n");
1947        break;
1948    }
1949    /* we should also setup the interleaving requirements based on the source format */
1950    if (ctx->eFormat == IMG_CODEC_PL12) /* FIXME contrary with old DDK, take notice */
1951        psSliceParams->Flags |= INTERLEAVE_TARGET;
1952
1953    cmdbuf = ctx->obj_context->pnw_cmdbuf;
1954
1955    RELOC_SLICE_PARAMS_PNW(&(psSliceParams->RefYBase), 256 * RowOffset / 16, psRef);
1956    RELOC_SLICE_PARAMS_PNW(&(psSliceParams->RefUVBase),
1957                           ref_surface->psb_surface->stride * ref_surface->height + (RowOffset * 128 / 16),
1958                           psRef);
1959    if (IsIntra)
1960        RELOC_SLICE_PARAMS_PNW(&(psSliceParams->InParamsBase),
1961                               ctx->in_params_ofs,
1962                               //((CurrentRow * (ctx->Width)) / 256 + ctx->obj_context->slice_count) * sizeof(MTX_CURRENT_IN_PARAMS),
1963                               cmdbuf->topaz_in_params_I);
1964    else
1965        RELOC_SLICE_PARAMS_PNW(&(psSliceParams->InParamsBase),
1966                               ctx->in_params_ofs,
1967                               //((CurrentRow * (ctx->Width)) / 256 + ctx->obj_context->slice_count) * sizeof(MTX_CURRENT_IN_PARAMS),
1968                               cmdbuf->topaz_in_params_P);
1969
1970#if  TOPAZ_PIC_PARAMS_VERBOSE
1971    drv_debug_msg(VIDEO_DEBUG_GENERAL, "sizeof psSliceParams %d\n", sizeof(*psSliceParams));
1972    drv_debug_msg(VIDEO_DEBUG_GENERAL, "sizeof MTX_CURRENT_IN_PARAMS %d\n", sizeof(MTX_CURRENT_IN_PARAMS));
1973    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->SliceStartRowNum %d\n", psSliceParams->SliceStartRowNum);
1974    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->SliceHeight %d\n", psSliceParams->SliceHeight);
1975    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->RefYBase %x\n", psSliceParams->RefYBase);
1976    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->RefUVBase %x\n", psSliceParams->RefUVBase);
1977    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->RefYStride %d\n", psSliceParams->RefYStride);
1978    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->RefUVStride %d\n", psSliceParams->RefUVStride);
1979    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->RefYRowStride %d\n", psSliceParams->RefYRowStride);
1980    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->RefUVRowStride %d\n", psSliceParams->RefUVRowStride);
1981    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->HostCtx %x\n", psSliceParams->HostCtx);
1982    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->Flags %x\n", psSliceParams->Flags);
1983    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->MaxSliceSize %d\n",  psSliceParams->MaxSliceSize);
1984    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->FCode %x\n", psSliceParams->FCode);
1985    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->InParamsBase %x\n", psSliceParams->InParamsBase);
1986    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->NumAirMBs %d\n", psSliceParams->NumAirMBs);
1987    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->AirThreshold %x\n", psSliceParams->AirThreshold);
1988    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->ScanningIntraParams %x\n", psSliceParams->ScanningIntraParams);
1989#endif
1990
1991    pnw_cmdbuf_insert_command_package(ctx->obj_context,
1992                                      ctx->SliceToCore,
1993                                      MTX_CMDID_ENCODE_SLICE,
1994                                      &cmdbuf->slice_params,
1995                                      CurrentSlice *((sizeof(SLICE_PARAMS) + 15) & 0xfff0));
1996
1997
1998    return 0;
1999}
2000
2001
2002
2003/*
2004 * Function Name      : Reset_EncoderParams
2005 * Description        : Reset Above & Below Params at the Start of Intra frame
2006 */
2007void pnw_reset_encoder_params(context_ENC_p ctx)
2008{
2009    unsigned char *Add_Below, *Add_Above;
2010    pnw_cmdbuf_p cmdbuf = ctx->obj_context->pnw_cmdbuf;
2011
2012    /* all frames share the same Topaz param, in_param/aboveparam/bellow
2013     * map it only when necessary
2014     */
2015    if (cmdbuf->topaz_above_params_p == NULL) {
2016        VAStatus vaStatus = psb_buffer_map(cmdbuf->topaz_above_params, &cmdbuf->topaz_above_params_p);
2017        if (vaStatus != VA_STATUS_SUCCESS) {
2018            drv_debug_msg(VIDEO_DEBUG_ERROR, "map topaz MTX_CURRENT_IN_PARAMS failed\n");
2019            return;
2020        }
2021    }
2022
2023    if (cmdbuf->topaz_below_params_p == NULL) {
2024        VAStatus vaStatus = psb_buffer_map(cmdbuf->topaz_below_params, &cmdbuf->topaz_below_params_p);
2025        if (vaStatus != VA_STATUS_SUCCESS) {
2026            drv_debug_msg(VIDEO_DEBUG_ERROR, "map topaz MTX_CURRENT_IN_PARAMS failed\n");
2027            return;
2028        }
2029    }
2030
2031    Add_Below = cmdbuf->topaz_below_params_p +
2032                ctx->below_params_ofs;
2033
2034    memset(Add_Below, 0, ctx->below_params_size * 4);
2035
2036    Add_Above = cmdbuf->topaz_above_params_p + ctx->above_params_ofs;
2037    memset(Add_Above, 0, ctx->above_params_size * MAX_TOPAZ_CORES);
2038}
2039
2040
2041
2042