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 *    Zeng Li <zeng.li@intel.com>
27 *
28 */
29
30#include "psb_cmdbuf.h"
31
32#include <unistd.h>
33#include <stdio.h>
34
35#include "hwdefs/mem_io.h"
36#include "hwdefs/msvdx_offsets.h"
37#include "hwdefs/reg_io2.h"
38#include "hwdefs/msvdx_vec_reg_io2.h"
39#include "hwdefs/msvdx_vdmc_reg_io2.h"
40#include "hwdefs/msvdx_mtx_reg_io2.h"
41#include "hwdefs/msvdx_dmac_linked_list.h"
42#include "hwdefs/msvdx_rendec_mtx_slice_cntrl_reg_io2.h"
43#include "hwdefs/msvdx_core_regs_io2.h"
44#include "hwdefs/h264_macroblock_mem_io.h"
45#include "hwdefs/dxva_cmdseq_msg.h"
46#include "hwdefs/dxva_fw_ctrl.h"
47#include "hwdefs/fwrk_msg_mem_io.h"
48#include "hwdefs/dxva_msg.h"
49#include "hwdefs/msvdx_cmds_io2.h"
50#include <stdlib.h>
51#include <errno.h>
52#include <string.h>
53
54#include "psb_def.h"
55#include "psb_drv_debug.h"
56
57#define H264_MACROBLOCK_DATA_SIZE       0x80
58
59#define MSVDX_CMDS_BASE         0x1000
60#define MSVDX_CORE_BASE         0x600
61#define MSVDX_VEC_BASE          0x800
62
63#define MSVDX_DEBLOCK_REG_SET   0x10000000
64#define MSVDX_DEBLOCK_REG_GET   0x20000000
65#define MSVDX_DEBLOCK_REG_POLLn 0x30000000
66#define MSVDX_DEBLOCK_REG_POLLx 0x40000000
67
68static int reg_set_count = 0;
69static int reg_get_count = 0;
70static int reg_poll_x = 0;
71static int reg_poll_n = 0;
72
73#define psb_deblock_reg_set(group, reg, value) \
74        *cmdbuf->regio_idx++ = (group##_##reg##_##OFFSET + group##_##BASE) | MSVDX_DEBLOCK_REG_SET;     \
75        *cmdbuf->regio_idx++ = value; reg_set_count++;
76
77#define psb_deblock_reg_set_RELOC( group, reg, buffer, buffer_offset, dst)             \
78        *cmdbuf->regio_idx++ = (group##_##reg##_##OFFSET + group##_##BASE) | MSVDX_DEBLOCK_REG_SET;  \
79        RELOC_REGIO(*cmdbuf->regio_idx++, buffer_offset, buffer, dst); reg_set_count++;
80
81#define psb_deblock_reg_table_set(group, reg, index, value)             \
82        *cmdbuf->regio_idx++ = ( (group##_##reg##_OFFSET + group##_##BASE + index*group##_##reg##_STRIDE) | MSVDX_DEBLOCK_REG_SET); \
83        *cmdbuf->regio_idx++ = value; reg_set_count++;
84
85#define psb_deblock_reg_get(group, reg) \
86        *cmdbuf->regio_idx++ = (group##_##reg##_##OFFSET + group##_##BASE) | MSVDX_DEBLOCK_REG_GET; reg_get_count++;
87
88#if 1
89#define h264_pollForSpaceForNCommands(NumCommands)\
90        *cmdbuf->regio_idx++ = (MSVDX_CORE_CR_MSVDX_COMMAND_SPACE_OFFSET + MSVDX_CORE_BASE) | MSVDX_DEBLOCK_REG_POLLn; \
91        *cmdbuf->regio_idx++ = NumCommands; reg_poll_n++;
92#else
93#define h264_pollForSpaceForNCommands(NumCommands)              /* Seems not needed, so just define it null */
94#endif
95
96#define PollForSpaceForXCommands  \
97        *cmdbuf->regio_idx++ = (MSVDX_CORE_CR_MSVDX_COMMAND_SPACE_OFFSET + MSVDX_CORE_BASE) | MSVDX_DEBLOCK_REG_POLLx; reg_poll_x++;
98
99typedef enum {
100    H264_BLOCKSIZE_16X16                = 0, /* 1 block */
101    H264_BLOCKSIZE_16X8                 = 1, /* 2 blocks */
102    H264_BLOCKSIZE_8X16                 = 2,
103    H264_BLOCKSIZE_8X8                  = 3, /* 4 blocks */
104    H264_BLOCKSIZE_8X4                  = 4,
105    H264_BLOCKSIZE_4X8                  = 5,
106    H264_BLOCKSIZE_4X4                  = 6
107
108} h264_eBlockSize;
109
110static  uint32_t        BlockDownsizeMap[] = {
111    1, 1, 3, 3, 3, 5, 5
112};
113
114static  uint32_t        BlocksToSendMap[] = {
115    1, 2, 2, 4, 4, 4, 4
116};
117
118static  uint32_t        BlockAddressMap[7][4] = {
119    { 0 },                                                                                      /* 16x16        */
120    { 0, 2 },                                                                           /* 16x8         */
121    { 0, 1 },                                                                           /* 8x16         */
122    { 0, 1, 2, 3 },                                                                     /* 8x8          */
123    { 0, 1, 2, 3 },                                                                     /* 8x4          */
124    { 0, 1, 2, 3 },                                                                     /* 4x8          */
125    { 0, 1, 2, 3 }                                                                      /* 4x4          */
126};
127
128static  uint32_t        VectorsToSendMap[] = {
129    1, 1, 1, 1, 2, 2, 4
130};
131
132static  uint32_t        VectorOffsetMap[7][4] = {
133    { 0 },                                                                                      /* 16x16        */
134    { 0 },                                                                                      /* 16x8         */
135    { 0 },                                                                                      /* 8x16         */
136    { 0 },                                                                                      /* 8x8          */
137    { 0, 2 },                                                                           /* 8x4          */
138    { 0, 1 },                                                                           /* 4x8          */
139    { 0, 1, 2, 3 }                                                                      /* 4x4          */
140};
141
142
143static  uint32_t        Above1AboveTileMap[] = {
144    /*  9, 12, 8, 13    */
145    13, 12, 9, 8
146};
147
148static  uint32_t        CurrentAboveTileMap[] = {
149    /*  11, 14, 10, 15  */
150    15, 14, 11, 10
151};
152
153static  uint32_t        CurrentColTileMap[] = {
154    10, 15, 0, 5, 8, 13, 2, 7, 1, 4, 3, 6, 9, 12
155};
156
157
158static  uint32_t        ColBlockMap[] = {
159    2, 3, 0, 1
160};
161
162void
163h264_above1InterBlockSequence(psb_cmdbuf_p cmdbuf, uint8_t* MbData)
164{
165    uint32_t    i, BlockNum, Mv, MvAddr, Value;
166    uint32_t    Block8x8, blockType;
167    uint32_t    InterBlockCmd;
168    uint32_t    MotionVecCmd[16];
169    uint32_t    BlockType[4] = {0};
170    uint32_t    DpbIdx[4];
171
172    /* set MV vars to 0 */
173    for (i = 0; i < 16; i++) {
174        MotionVecCmd[i] = 0;
175    }
176
177    /* Read the size of blocks 2 and 3 and resize them so they are all ?x8 */
178    Value = MEMIO_READ_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_ASO_BLOCK2_PREDICTION_SIZE);
179    if (Value > (sizeof(BlockDownsizeMap) / sizeof(uint32_t) - 1))
180        Value = sizeof(BlockDownsizeMap) / sizeof(uint32_t) - 1;
181    BlockType[2] = BlockDownsizeMap[Value];
182    Value = MEMIO_READ_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_ASO_BLOCK3_PREDICTION_SIZE);
183    if (Value > (sizeof(BlockDownsizeMap) / sizeof(uint32_t) - 1))
184        Value = sizeof(BlockDownsizeMap) / sizeof(uint32_t) - 1;
185    BlockType[3] = BlockDownsizeMap[Value];
186
187    /* read motion vectors for the bottom row, but store them in the correct locn. for ?x8 blocks */
188    for (i = 0; i < 4; i++) {
189        Value = MEMIO_READ_TABLE_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_COMP_X_ABOVE, i);
190        REGIO_WRITE_FIELD(MotionVecCmd[Above1AboveTileMap[i]], MSVDX_CMDS, MOTION_VECTOR, MV_X, Value);
191        Value = MEMIO_READ_TABLE_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_COMP_Y_ABOVE, i);
192        REGIO_WRITE_FIELD(MotionVecCmd[Above1AboveTileMap[i]], MSVDX_CMDS, MOTION_VECTOR, MV_Y, Value);
193    }
194
195    /* read DPB index for blocks 2 and 3 */
196    for (i = 0; i < 2; i++) {
197        DpbIdx[ColBlockMap[i]] = MEMIO_READ_TABLE_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_DPB_IDX_COL, i);
198    }
199
200    /* Send commands required blocks */
201    for (BlockNum = BlocksToSendMap[BlockType[2]] / 2;
202         BlockNum < BlocksToSendMap[BlockType[2]];
203         BlockNum++) {
204        /* block address */
205        Block8x8 = BlockAddressMap[BlockType[2]][BlockNum];
206        /* block type */
207        blockType = BlockType[Block8x8];
208
209        InterBlockCmd = 0;
210        REGIO_WRITE_FIELD(InterBlockCmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, INTER_PRED_BLOCK_SIZE, blockType);
211        REGIO_WRITE_FIELD(InterBlockCmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_A_VALID, 1);
212        REGIO_WRITE_FIELD(InterBlockCmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_A, DpbIdx[Block8x8]);
213
214        /* send commands */
215        h264_pollForSpaceForNCommands(1 + VectorsToSendMap[blockType]);
216        psb_deblock_reg_table_set(MSVDX_CMDS, INTER_BLOCK_PREDICTION_ABOVE1, Block8x8, InterBlockCmd);
217
218        for (i = 0; i < VectorsToSendMap[blockType]; i++) {
219            /* only send forward MVs in baseline */
220            MvAddr = (2 * 4 * Block8x8) + VectorOffsetMap[blockType][i];
221            Mv = (4 * Block8x8) + VectorOffsetMap[blockType][i];
222            psb_deblock_reg_table_set(MSVDX_CMDS, MOTION_VECTOR_ABOVE1, MvAddr, MotionVecCmd[Mv]);
223        }
224    }
225}
226
227void
228h264_currentInterBlockSequence(psb_cmdbuf_p cmdbuf, uint8_t * MbData)
229{
230    uint32_t    i, BlockNum, Mv, MvAddr, Value;
231    uint32_t    Block8x8, blockType;
232    uint32_t    InterBlockCmd;
233    uint32_t    MotionVecCmd[16];
234    uint32_t    BlockType[4];
235    uint32_t    DpbIdx[4];
236
237    /* set MV vars to 0 */
238    for (i = 0; i < 16; i++) {
239        MotionVecCmd[i] = 0;
240    }
241
242    /* read block size */
243    BlockType[0] = MEMIO_READ_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_ASO_BLOCK0_PREDICTION_SIZE);
244    BlockType[1] = MEMIO_READ_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_ASO_BLOCK1_PREDICTION_SIZE);
245    BlockType[2] = MEMIO_READ_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_ASO_BLOCK2_PREDICTION_SIZE);
246    BlockType[3] = MEMIO_READ_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_ASO_BLOCK3_PREDICTION_SIZE);
247
248    /* read motion vectors in all 16 4x4 sub-blocks*/
249    for (i = 1; i < 3; i++) {   /* get blocks 11 and 14 */
250        Value = MEMIO_READ_TABLE_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_COMP_X_ABOVE, i);
251        REGIO_WRITE_FIELD(MotionVecCmd[CurrentAboveTileMap[i]], MSVDX_CMDS, MOTION_VECTOR, MV_X, Value);
252        Value = MEMIO_READ_TABLE_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_COMP_Y_ABOVE, i);
253        REGIO_WRITE_FIELD(MotionVecCmd[CurrentAboveTileMap[i]], MSVDX_CMDS, MOTION_VECTOR, MV_Y, Value);
254    }
255    for (i = 0; i < 14; i++) {
256        Value = MEMIO_READ_TABLE_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_COMP_X_COL, i);
257        REGIO_WRITE_FIELD(MotionVecCmd[CurrentColTileMap[i]], MSVDX_CMDS, MOTION_VECTOR, MV_X, Value);
258        Value = MEMIO_READ_TABLE_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_COMP_Y_COL, i);
259        REGIO_WRITE_FIELD(MotionVecCmd[CurrentColTileMap[i]], MSVDX_CMDS, MOTION_VECTOR, MV_Y, Value);
260    }
261
262    /* read DPB index for all 4 blocks */
263    for (i = 0; i < 4; i++) {
264        DpbIdx[ColBlockMap[i]] = MEMIO_READ_TABLE_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_DPB_IDX_COL, i);
265    }
266
267    /* Send commands required blocks */
268    for (BlockNum = 0;
269         BlockNum < BlocksToSendMap[BlockType[0]];
270         BlockNum++) {
271        /* block address */
272        Block8x8 = BlockAddressMap[BlockType[0]][BlockNum];
273        /* block type */
274        blockType = BlockType[Block8x8];
275
276        InterBlockCmd = 0;
277        REGIO_WRITE_FIELD(InterBlockCmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, INTER_PRED_BLOCK_SIZE, blockType);
278        REGIO_WRITE_FIELD(InterBlockCmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_A_VALID, 1);
279        REGIO_WRITE_FIELD(InterBlockCmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_A, DpbIdx[Block8x8]);
280
281        /* send commands */
282        h264_pollForSpaceForNCommands(1 + VectorsToSendMap[blockType]);
283        psb_deblock_reg_table_set(MSVDX_CMDS, INTER_BLOCK_PREDICTION, Block8x8, InterBlockCmd);
284
285        for (i = 0; i < VectorsToSendMap[blockType]; i++) {
286            /* only send forward MVs in baseline */
287            MvAddr = (2 * 4 * Block8x8) + VectorOffsetMap[blockType][i];
288            Mv = (4 * Block8x8) + VectorOffsetMap[blockType][i];
289            psb_deblock_reg_table_set(MSVDX_CMDS, MOTION_VECTOR, MvAddr, MotionVecCmd[Mv]);
290        }
291    }
292}
293
294void
295h264_currentIntraBlockPrediction(psb_cmdbuf_p cmdbuf, uint8_t * MbData, int bMbIsIPCM)
296{
297    uint32_t    BlockSizeY, BlockSizeC;
298    uint32_t    IntraCmdY, IntraCmdC;
299
300    /* select block size I_PCM or I_16x16 */
301    BlockSizeY = (1 == bMbIsIPCM) ? 3 : 0;
302    /* select block size I_PCM or I_8x8 */
303    BlockSizeC = (1 == bMbIsIPCM) ? 3 : 1;
304
305    IntraCmdY = IntraCmdC = 0;
306
307    REGIO_WRITE_FIELD(
308        IntraCmdY,
309        MSVDX_CMDS, INTRA_BLOCK_PREDICTION,
310        INTRA_PRED_BLOCK_SIZE,
311        BlockSizeY);
312    REGIO_WRITE_FIELD(
313        IntraCmdC,
314        MSVDX_CMDS, INTRA_BLOCK_PREDICTION,
315        INTRA_PRED_BLOCK_SIZE,
316        BlockSizeC);
317
318    h264_pollForSpaceForNCommands(2);
319    psb_deblock_reg_table_set(MSVDX_CMDS, INTRA_BLOCK_PREDICTION, 0, IntraCmdY);
320    psb_deblock_reg_table_set(MSVDX_CMDS, INTRA_BLOCK_PREDICTION, 4, IntraCmdC);
321}
322
323void
324h264_above1IntraBlockPrediction(psb_cmdbuf_p cmdbuf, uint8_t * MbData, int bMbIsIPCM)
325{
326    uint32_t    BlockSizeY;
327    uint32_t    IntraCmdY;
328
329    /* select block size I_PCM or I_16x16 */
330    BlockSizeY = (1 == bMbIsIPCM) ? 3 : 0;
331    IntraCmdY = 0;
332
333    REGIO_WRITE_FIELD(
334        IntraCmdY,
335        MSVDX_CMDS, INTRA_BLOCK_PREDICTION_ABOVE1,
336        INTRA_PRED_BLOCK_SIZE_ABOVE1,
337        BlockSizeY);
338
339    h264_pollForSpaceForNCommands(1);
340    psb_deblock_reg_table_set(MSVDX_CMDS, INTRA_BLOCK_PREDICTION_ABOVE1, 0, IntraCmdY);
341}
342
343void
344h264_macroblockCmdSequence(psb_cmdbuf_p cmdbuf, uint8_t * MbData, uint32_t X, uint32_t  Y, int bCurrent)
345{
346    int bMbIsIPCM;
347    uint32_t    MbType;
348    uint32_t    Value;
349    uint32_t    MbNumberCmd, MbQuantCmd, MbTransZeroCmd;
350
351    /* Macroblock Type */
352    MbType  = MEMIO_READ_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_MBTYPE);
353
354    /* Macroblock Number */
355    /* no need for MB_ERROR_FLAG as error info is not stored */
356    /* no need for MB_FIELD_CODE as basline is always frame based */
357    MbNumberCmd = 0;
358
359    Value = (3 == MbType) ? 0 : MbType;
360    REGIO_WRITE_FIELD(MbNumberCmd, MSVDX_CMDS, MACROBLOCK_NUMBER, MB_CODE_TYPE, Value);
361
362    REGIO_WRITE_FIELD(MbNumberCmd, MSVDX_CMDS, MACROBLOCK_NUMBER, MB_NO_Y, Y);
363    REGIO_WRITE_FIELD(MbNumberCmd, MSVDX_CMDS, MACROBLOCK_NUMBER, MB_NO_X, X);
364
365    /* H264 Quant */
366    /* TRANSFORM_SIZE_8X8 always false in basline */
367    MbQuantCmd = 0;
368
369    Value = MEMIO_READ_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_QP_CR);
370    REGIO_WRITE_FIELD(MbQuantCmd, MSVDX_CMDS, MACROBLOCK_H264_QUANT, MB_QUANT_CHROMA_CR, Value);
371
372    Value = MEMIO_READ_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_QP_CB);
373    REGIO_WRITE_FIELD(MbQuantCmd, MSVDX_CMDS, MACROBLOCK_H264_QUANT, MB_QUANT_CHROMA_CB, Value);
374
375    Value = MEMIO_READ_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_QP);
376    REGIO_WRITE_FIELD(MbQuantCmd, MSVDX_CMDS, MACROBLOCK_H264_QUANT, MB_QUANT_LUMA, Value);
377
378    /* send 2 commands */
379    h264_pollForSpaceForNCommands(2);
380    if (1 == bCurrent) {
381        /* Top and Left available flags are only sent for current MB */
382        Value = MEMIO_READ_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_MB_AVAILABLE_TOP_FLAG);
383        Value = (1 == Value) ? 0 : 1;
384        REGIO_WRITE_FIELD(MbNumberCmd, MSVDX_CMDS, MACROBLOCK_NUMBER, MB_SLICE_TOP, Value);
385
386        Value = MEMIO_READ_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_MB_AVAILABLE_LEFT_FLAG);
387        Value = (1 == Value) ? 0 : 1;
388        REGIO_WRITE_FIELD(MbNumberCmd, MSVDX_CMDS, MACROBLOCK_NUMBER, MB_SLICE_LHS, Value);
389
390        psb_deblock_reg_set(MSVDX_CMDS, MACROBLOCK_NUMBER, MbNumberCmd);
391        psb_deblock_reg_set(MSVDX_CMDS, MACROBLOCK_H264_QUANT, MbQuantCmd);
392    } else {
393        psb_deblock_reg_set(MSVDX_CMDS, MACROBLOCK_NUMBER_ABOVE1, MbNumberCmd);
394        psb_deblock_reg_set(MSVDX_CMDS, MACROBLOCK_H264_QUANT_ABOVE1, MbQuantCmd);
395    }
396
397    /* Prediction Block Sequence */
398    bMbIsIPCM = 0;
399    switch (MbType) {
400    case 3:             /* IPCM */
401        bMbIsIPCM = 1;
402        /* deliberate drop through */
403    case 0:             /* I */
404        if (1 == bCurrent) {
405            h264_currentIntraBlockPrediction(cmdbuf, MbData, bMbIsIPCM);
406        } else {
407            h264_above1IntraBlockPrediction(cmdbuf, MbData, bMbIsIPCM);
408        }
409        break;
410    case 1:             /* P */
411        if (1 == bCurrent) {
412            h264_currentInterBlockSequence(cmdbuf, MbData);
413        } else {
414            h264_above1InterBlockSequence(cmdbuf, MbData);
415        }
416        break;
417    case 2:             /* B */
418    default:
419        /* invalid MB type */
420        //IMG_ASSERT( 0 );
421        break;
422    }
423
424    /* Trasform Zero */
425    MbTransZeroCmd = 0;
426    Value = MEMIO_READ_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_ASO_MB_TRANSFORM_ZERO);
427    REGIO_WRITE_FIELD(MbTransZeroCmd, MSVDX_CMDS, MACROBLOCK_BLOCK_TRANSFORM_ZERO, MB_BLOCK_TRANSFORM_ZERO, Value);
428
429    /* write last command */
430    h264_pollForSpaceForNCommands(1);
431    if (1 == bCurrent) {
432        psb_deblock_reg_set(MSVDX_CMDS, MACROBLOCK_BLOCK_TRANSFORM_ZERO, MbTransZeroCmd);
433    } else {
434        MbTransZeroCmd &= 0x0000CC00;   /* only send for sub-blocks 10,11,14 and 15 */
435        psb_deblock_reg_set(MSVDX_CMDS, MACROBLOCK_BLOCK_TRANSFORM_ZERO_ABOVE1, MbTransZeroCmd);
436    }
437}
438
439uint32_t
440h264_getCurrentSliceCmd(uint8_t* MbData)
441{
442    uint32_t    Value, Cmd;
443
444    Cmd = 0;
445
446    /* unpack data from stored MB + repack in command */
447    Value = MEMIO_READ_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_COPY_DISABLE_DEBLOCK_FILTER_IDC);
448    REGIO_WRITE_FIELD(Cmd, MSVDX_CMDS, SLICE_PARAMS, DISABLE_DEBLOCK_FILTER_IDC, Value);
449
450    Value = MEMIO_READ_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_COPY_H264_BE_SLICE0_ALPHA_CO_OFFSET_DIV2);
451    REGIO_WRITE_FIELD(Cmd, MSVDX_CMDS, SLICE_PARAMS, SLICE_ALPHA_CO_OFFSET_DIV2, Value);
452
453    Value = MEMIO_READ_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_COPY_H264_BE_SLICE0_BETA_OFFSET_DIV2);
454    REGIO_WRITE_FIELD(Cmd, MSVDX_CMDS, SLICE_PARAMS, SLICE_BETA_OFFSET_DIV2, Value);
455
456    Value = MEMIO_READ_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_COPY_H264_BE_SLICE0_FIELD_TYPE);
457    REGIO_WRITE_FIELD(Cmd, MSVDX_CMDS, SLICE_PARAMS, SLICE_FIELD_TYPE, Value);
458
459    Value = MEMIO_READ_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_COPY_H264_BE_SLICE0_CODE_TYPE);
460    REGIO_WRITE_FIELD(Cmd, MSVDX_CMDS, SLICE_PARAMS, SLICE_CODE_TYPE, Value);
461
462    return Cmd;
463}
464
465int h264_secondPass(
466    psb_cmdbuf_p cmdbuf,
467    uint8_t     * MbData,
468    uint32_t    OperatingModeCmd,
469    uint32_t    Width,
470    uint32_t    Height
471)
472{
473    uint32_t    i, PicSize;
474    uint32_t    EndOfPictureCmd;
475    uint32_t    EndOfSliceCmd;
476    uint32_t    SliceCmd, OldSliceCmd;
477    uint32_t    EnableReg;
478    uint8_t     * CurrMb;
479    uint8_t     * Above1Mb;
480    int bRetCode = 0;
481
482    PicSize = Width * Height;
483
484    /* End of Slice command */
485    EndOfSliceCmd = 0;
486    REGIO_WRITE_FIELD(EndOfSliceCmd, MSVDX_CMDS, END_SLICE_PICTURE, PICTURE_END, 0);
487
488
489    /* put vdeb into second pass mode */
490    /* send operating mode command for VDEB only */
491    REGIO_WRITE_FIELD(OperatingModeCmd,  MSVDX_CMDS, OPERATING_MODE, ASYNC_MODE, 2);   /* VDEB only */
492    h264_pollForSpaceForNCommands(1);
493    psb_deblock_reg_get(MSVDX_CORE, CR_MSVDX_COMMAND_SPACE);
494    psb_deblock_reg_set(MSVDX_CMDS, OPERATING_MODE, OperatingModeCmd);
495
496    PollForSpaceForXCommands;
497
498    /* Send Slice Command */
499    SliceCmd = h264_getCurrentSliceCmd(MbData);
500    h264_pollForSpaceForNCommands(2);
501    psb_deblock_reg_set(MSVDX_CMDS, SLICE_PARAMS, SliceCmd);
502    psb_deblock_reg_set(MSVDX_CMDS, SLICE_PARAMS_ABOVE1, SliceCmd);
503    /* process top row */
504    for (i = 0, CurrMb = MbData;
505         i < Width;
506         i++, CurrMb += H264_MACROBLOCK_DATA_SIZE) {
507        OldSliceCmd = SliceCmd;
508        SliceCmd = h264_getCurrentSliceCmd(CurrMb);
509        if (OldSliceCmd != SliceCmd) {
510            h264_pollForSpaceForNCommands(2);
511            psb_deblock_reg_set(MSVDX_CMDS, END_SLICE_PICTURE, EndOfSliceCmd);
512            psb_deblock_reg_set(MSVDX_CMDS, SLICE_PARAMS, SliceCmd);
513        }
514
515        h264_macroblockCmdSequence(cmdbuf, CurrMb, i, 0, 1);
516    }
517
518    /* process rest of picture */
519    for (Above1Mb = MbData;
520         i < PicSize;
521         i++, CurrMb += H264_MACROBLOCK_DATA_SIZE, Above1Mb += H264_MACROBLOCK_DATA_SIZE) {
522        OldSliceCmd = SliceCmd;
523        SliceCmd = h264_getCurrentSliceCmd(CurrMb);
524        if (OldSliceCmd != SliceCmd) {
525            h264_pollForSpaceForNCommands(2);
526            psb_deblock_reg_set(MSVDX_CMDS, END_SLICE_PICTURE, EndOfSliceCmd);
527            psb_deblock_reg_set(MSVDX_CMDS, SLICE_PARAMS, SliceCmd);
528        }
529
530        h264_macroblockCmdSequence(cmdbuf, Above1Mb, (i % Width), (i / Width) - 1, 0);
531        h264_macroblockCmdSequence(cmdbuf, CurrMb, (i % Width), (i / Width), 1);
532    }
533
534    /* send end of pic + restart back end */
535    EndOfPictureCmd = 0;
536    EnableReg = 0;
537    REGIO_WRITE_FIELD(EndOfPictureCmd, MSVDX_CMDS, END_SLICE_PICTURE, PICTURE_END, 1);
538    REGIO_WRITE_FIELD(EnableReg, MSVDX_VEC, CR_VEC_CONTROL, ENTDEC_ENABLE_BE, 1);
539
540    h264_pollForSpaceForNCommands(2);
541    psb_deblock_reg_set(MSVDX_CMDS, END_SLICE_PICTURE, EndOfSliceCmd);
542    psb_deblock_reg_set(MSVDX_CMDS, END_SLICE_PICTURE, EndOfPictureCmd);
543    //psb_deblock_reg_set( MSVDX_VEC, CR_VEC_CONTROL, EnableReg);                       /* this is not a command */
544    return bRetCode;
545}
546
547int psb_cmdbuf_second_pass(object_context_p obj_context,
548                           uint32_t OperatingModeCmd,
549                           unsigned char * pvParamBase,
550                           uint32_t PicWidthInMbs,
551                           uint32_t FrameHeightInMbs,
552                           psb_buffer_p target_buffer,
553                           uint32_t chroma_offset
554                          )
555{
556    int bRetVal = 1;
557    uint32_t Cmd, item_loc;
558    uint32_t *cmd_size;
559    psb_cmdbuf_p cmdbuf =  obj_context->cmdbuf;
560
561    if (psb_buffer_map(&cmdbuf->regio_buf, &cmdbuf->regio_base)) {
562        //printf("map cmdbuf->regio_buf error\n");
563        return bRetVal;
564    }
565
566    item_loc = psb_cmdbuf_buffer_ref(cmdbuf, &cmdbuf->regio_buf);
567
568    cmdbuf->regio_idx = (uint32_t *)cmdbuf->regio_base;
569    cmd_size = cmdbuf->regio_idx++;
570
571    h264_pollForSpaceForNCommands(4);
572
573    psb_deblock_reg_set_RELOC(MSVDX_CMDS, LUMA_RECONSTRUCTED_PICTURE_BASE_ADDRESSES, target_buffer, target_buffer->buffer_ofs, item_loc);
574    psb_deblock_reg_set_RELOC(MSVDX_CMDS, CHROMA_RECONSTRUCTED_PICTURE_BASE_ADDRESSES, target_buffer, target_buffer->buffer_ofs + chroma_offset, item_loc);
575
576    Cmd = 0;
577    REGIO_WRITE_FIELD_LITE(Cmd, MSVDX_CMDS, DISPLAY_PICTURE_SIZE, DISPLAY_PICTURE_HEIGHT, (FrameHeightInMbs * 16) - 1);
578    REGIO_WRITE_FIELD_LITE(Cmd, MSVDX_CMDS, DISPLAY_PICTURE_SIZE, DISPLAY_PICTURE_WIDTH, (PicWidthInMbs * 16) - 1);
579    psb_deblock_reg_set(MSVDX_CMDS, DISPLAY_PICTURE_SIZE, Cmd);
580
581
582    Cmd = 0;
583    REGIO_WRITE_FIELD_LITE(Cmd, MSVDX_CMDS, CODED_PICTURE_SIZE, CODED_PICTURE_HEIGHT, (FrameHeightInMbs * 16) - 1);
584    REGIO_WRITE_FIELD_LITE(Cmd, MSVDX_CMDS, CODED_PICTURE_SIZE, CODED_PICTURE_WIDTH, (PicWidthInMbs * 16) - 1);
585    psb_deblock_reg_set(MSVDX_CMDS, CODED_PICTURE_SIZE, Cmd);
586
587    /* BRN25312 */
588    psb_deblock_reg_set(MSVDX_CMDS, VC1_LUMA_RANGE_MAPPING_BASE_ADDRESS, 0);
589    psb_deblock_reg_set(MSVDX_CMDS, VC1_CHROMA_RANGE_MAPPING_BASE_ADDRESS, 0);
590    psb_deblock_reg_set(MSVDX_CMDS, VC1_RANGE_MAPPING_FLAGS, 0);
591
592    /* process second pass */
593    bRetVal = h264_secondPass(cmdbuf,
594                              (uint8_t*)pvParamBase,
595                              OperatingModeCmd,
596                              PicWidthInMbs,
597                              FrameHeightInMbs);
598
599    *cmd_size = (cmdbuf->regio_idx - (uint32_t *)cmdbuf->regio_base - 1);
600
601    drv_debug_msg(VIDEO_DEBUG_GENERAL, "DEBLOCK: REGIO size is %d\n", (uint32_t)(cmdbuf->regio_idx - (uint32_t *)cmdbuf->regio_base) - 1);
602    //printf("DEBLOCK: REGIO size is %d\n", (uint32_t)(cmdbuf->regio_idx - (uint32_t *)cmdbuf->regio_base) - 1);
603    psb_buffer_unmap(&cmdbuf->regio_buf);
604    return bRetVal;
605}
606