| /* |
| * Copyright (c) 2011 Intel Corporation. All Rights Reserved. |
| * Copyright (c) Imagination Technologies Limited, UK |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a |
| * copy of this software and associated documentation files (the |
| * "Software"), to deal in the Software without restriction, including |
| * without limitation the rights to use, copy, modify, merge, publish, |
| * distribute, sub license, and/or sell copies of the Software, and to |
| * permit persons to whom the Software is furnished to do so, subject to |
| * the following conditions: |
| * |
| * The above copyright notice and this permission notice (including the |
| * next paragraph) shall be included in all copies or substantial portions |
| * of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. |
| * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR |
| * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
| * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
| * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| * |
| * Authors: |
| * Zeng Li <zeng.li@intel.com> |
| * |
| */ |
| |
| #include "psb_cmdbuf.h" |
| |
| #include <unistd.h> |
| #include <stdio.h> |
| |
| #include "hwdefs/mem_io.h" |
| #include "hwdefs/msvdx_offsets.h" |
| #include "hwdefs/reg_io2.h" |
| #include "hwdefs/msvdx_vec_reg_io2.h" |
| #include "hwdefs/msvdx_vdmc_reg_io2.h" |
| #include "hwdefs/msvdx_mtx_reg_io2.h" |
| #include "hwdefs/msvdx_dmac_linked_list.h" |
| #include "hwdefs/msvdx_rendec_mtx_slice_cntrl_reg_io2.h" |
| #include "hwdefs/msvdx_core_regs_io2.h" |
| #include "hwdefs/h264_macroblock_mem_io.h" |
| #include "hwdefs/dxva_cmdseq_msg.h" |
| #include "hwdefs/dxva_fw_ctrl.h" |
| #include "hwdefs/fwrk_msg_mem_io.h" |
| #include "hwdefs/dxva_msg.h" |
| #include "hwdefs/msvdx_cmds_io2.h" |
| #include <stdlib.h> |
| #include <errno.h> |
| #include <string.h> |
| |
| #include "psb_def.h" |
| #include "psb_drv_debug.h" |
| |
| #define H264_MACROBLOCK_DATA_SIZE 0x80 |
| |
| #define MSVDX_CMDS_BASE 0x1000 |
| #define MSVDX_CORE_BASE 0x600 |
| #define MSVDX_VEC_BASE 0x800 |
| |
| #define MSVDX_DEBLOCK_REG_SET 0x10000000 |
| #define MSVDX_DEBLOCK_REG_GET 0x20000000 |
| #define MSVDX_DEBLOCK_REG_POLLn 0x30000000 |
| #define MSVDX_DEBLOCK_REG_POLLx 0x40000000 |
| |
| static int reg_set_count = 0; |
| static int reg_get_count = 0; |
| static int reg_poll_x = 0; |
| static int reg_poll_n = 0; |
| |
| #define psb_deblock_reg_set(group, reg, value) \ |
| *cmdbuf->regio_idx++ = (group##_##reg##_##OFFSET + group##_##BASE) | MSVDX_DEBLOCK_REG_SET; \ |
| *cmdbuf->regio_idx++ = value; reg_set_count++; |
| |
| #define psb_deblock_reg_set_RELOC( group, reg, buffer, buffer_offset, dst) \ |
| *cmdbuf->regio_idx++ = (group##_##reg##_##OFFSET + group##_##BASE) | MSVDX_DEBLOCK_REG_SET; \ |
| RELOC_REGIO(*cmdbuf->regio_idx++, buffer_offset, buffer, dst); reg_set_count++; |
| |
| #define psb_deblock_reg_table_set(group, reg, index, value) \ |
| *cmdbuf->regio_idx++ = ( (group##_##reg##_OFFSET + group##_##BASE + index*group##_##reg##_STRIDE) | MSVDX_DEBLOCK_REG_SET); \ |
| *cmdbuf->regio_idx++ = value; reg_set_count++; |
| |
| #define psb_deblock_reg_get(group, reg) \ |
| *cmdbuf->regio_idx++ = (group##_##reg##_##OFFSET + group##_##BASE) | MSVDX_DEBLOCK_REG_GET; reg_get_count++; |
| |
| #if 1 |
| #define h264_pollForSpaceForNCommands(NumCommands)\ |
| *cmdbuf->regio_idx++ = (MSVDX_CORE_CR_MSVDX_COMMAND_SPACE_OFFSET + MSVDX_CORE_BASE) | MSVDX_DEBLOCK_REG_POLLn; \ |
| *cmdbuf->regio_idx++ = NumCommands; reg_poll_n++; |
| #else |
| #define h264_pollForSpaceForNCommands(NumCommands) /* Seems not needed, so just define it null */ |
| #endif |
| |
| #define PollForSpaceForXCommands \ |
| *cmdbuf->regio_idx++ = (MSVDX_CORE_CR_MSVDX_COMMAND_SPACE_OFFSET + MSVDX_CORE_BASE) | MSVDX_DEBLOCK_REG_POLLx; reg_poll_x++; |
| |
| typedef enum { |
| H264_BLOCKSIZE_16X16 = 0, /* 1 block */ |
| H264_BLOCKSIZE_16X8 = 1, /* 2 blocks */ |
| H264_BLOCKSIZE_8X16 = 2, |
| H264_BLOCKSIZE_8X8 = 3, /* 4 blocks */ |
| H264_BLOCKSIZE_8X4 = 4, |
| H264_BLOCKSIZE_4X8 = 5, |
| H264_BLOCKSIZE_4X4 = 6 |
| |
| } h264_eBlockSize; |
| |
| static uint32_t BlockDownsizeMap[] = { |
| 1, 1, 3, 3, 3, 5, 5 |
| }; |
| |
| static uint32_t BlocksToSendMap[] = { |
| 1, 2, 2, 4, 4, 4, 4 |
| }; |
| |
| static uint32_t BlockAddressMap[7][4] = { |
| { 0 }, /* 16x16 */ |
| { 0, 2 }, /* 16x8 */ |
| { 0, 1 }, /* 8x16 */ |
| { 0, 1, 2, 3 }, /* 8x8 */ |
| { 0, 1, 2, 3 }, /* 8x4 */ |
| { 0, 1, 2, 3 }, /* 4x8 */ |
| { 0, 1, 2, 3 } /* 4x4 */ |
| }; |
| |
| static uint32_t VectorsToSendMap[] = { |
| 1, 1, 1, 1, 2, 2, 4 |
| }; |
| |
| static uint32_t VectorOffsetMap[7][4] = { |
| { 0 }, /* 16x16 */ |
| { 0 }, /* 16x8 */ |
| { 0 }, /* 8x16 */ |
| { 0 }, /* 8x8 */ |
| { 0, 2 }, /* 8x4 */ |
| { 0, 1 }, /* 4x8 */ |
| { 0, 1, 2, 3 } /* 4x4 */ |
| }; |
| |
| |
| static uint32_t Above1AboveTileMap[] = { |
| /* 9, 12, 8, 13 */ |
| 13, 12, 9, 8 |
| }; |
| |
| static uint32_t CurrentAboveTileMap[] = { |
| /* 11, 14, 10, 15 */ |
| 15, 14, 11, 10 |
| }; |
| |
| static uint32_t CurrentColTileMap[] = { |
| 10, 15, 0, 5, 8, 13, 2, 7, 1, 4, 3, 6, 9, 12 |
| }; |
| |
| |
| static uint32_t ColBlockMap[] = { |
| 2, 3, 0, 1 |
| }; |
| |
| void |
| h264_above1InterBlockSequence(psb_cmdbuf_p cmdbuf, uint8_t* MbData) |
| { |
| uint32_t i, BlockNum, Mv, MvAddr, Value; |
| uint32_t Block8x8, blockType; |
| uint32_t InterBlockCmd; |
| uint32_t MotionVecCmd[16]; |
| uint32_t BlockType[4] = {0}; |
| uint32_t DpbIdx[4]; |
| |
| /* set MV vars to 0 */ |
| for (i = 0; i < 16; i++) { |
| MotionVecCmd[i] = 0; |
| } |
| |
| /* Read the size of blocks 2 and 3 and resize them so they are all ?x8 */ |
| Value = MEMIO_READ_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_ASO_BLOCK2_PREDICTION_SIZE); |
| if (Value > (sizeof(BlockDownsizeMap) / sizeof(uint32_t) - 1)) |
| Value = sizeof(BlockDownsizeMap) / sizeof(uint32_t) - 1; |
| BlockType[2] = BlockDownsizeMap[Value]; |
| Value = MEMIO_READ_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_ASO_BLOCK3_PREDICTION_SIZE); |
| if (Value > (sizeof(BlockDownsizeMap) / sizeof(uint32_t) - 1)) |
| Value = sizeof(BlockDownsizeMap) / sizeof(uint32_t) - 1; |
| BlockType[3] = BlockDownsizeMap[Value]; |
| |
| /* read motion vectors for the bottom row, but store them in the correct locn. for ?x8 blocks */ |
| for (i = 0; i < 4; i++) { |
| Value = MEMIO_READ_TABLE_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_COMP_X_ABOVE, i); |
| REGIO_WRITE_FIELD(MotionVecCmd[Above1AboveTileMap[i]], MSVDX_CMDS, MOTION_VECTOR, MV_X, Value); |
| Value = MEMIO_READ_TABLE_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_COMP_Y_ABOVE, i); |
| REGIO_WRITE_FIELD(MotionVecCmd[Above1AboveTileMap[i]], MSVDX_CMDS, MOTION_VECTOR, MV_Y, Value); |
| } |
| |
| /* read DPB index for blocks 2 and 3 */ |
| for (i = 0; i < 2; i++) { |
| DpbIdx[ColBlockMap[i]] = MEMIO_READ_TABLE_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_DPB_IDX_COL, i); |
| } |
| |
| /* Send commands required blocks */ |
| for (BlockNum = BlocksToSendMap[BlockType[2]] / 2; |
| BlockNum < BlocksToSendMap[BlockType[2]]; |
| BlockNum++) { |
| /* block address */ |
| Block8x8 = BlockAddressMap[BlockType[2]][BlockNum]; |
| /* block type */ |
| blockType = BlockType[Block8x8]; |
| |
| InterBlockCmd = 0; |
| REGIO_WRITE_FIELD(InterBlockCmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, INTER_PRED_BLOCK_SIZE, blockType); |
| REGIO_WRITE_FIELD(InterBlockCmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_A_VALID, 1); |
| REGIO_WRITE_FIELD(InterBlockCmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_A, DpbIdx[Block8x8]); |
| |
| /* send commands */ |
| h264_pollForSpaceForNCommands(1 + VectorsToSendMap[blockType]); |
| psb_deblock_reg_table_set(MSVDX_CMDS, INTER_BLOCK_PREDICTION_ABOVE1, Block8x8, InterBlockCmd); |
| |
| for (i = 0; i < VectorsToSendMap[blockType]; i++) { |
| /* only send forward MVs in baseline */ |
| MvAddr = (2 * 4 * Block8x8) + VectorOffsetMap[blockType][i]; |
| Mv = (4 * Block8x8) + VectorOffsetMap[blockType][i]; |
| psb_deblock_reg_table_set(MSVDX_CMDS, MOTION_VECTOR_ABOVE1, MvAddr, MotionVecCmd[Mv]); |
| } |
| } |
| } |
| |
| void |
| h264_currentInterBlockSequence(psb_cmdbuf_p cmdbuf, uint8_t * MbData) |
| { |
| uint32_t i, BlockNum, Mv, MvAddr, Value; |
| uint32_t Block8x8, blockType; |
| uint32_t InterBlockCmd; |
| uint32_t MotionVecCmd[16]; |
| uint32_t BlockType[4]; |
| uint32_t DpbIdx[4]; |
| |
| /* set MV vars to 0 */ |
| for (i = 0; i < 16; i++) { |
| MotionVecCmd[i] = 0; |
| } |
| |
| /* read block size */ |
| BlockType[0] = MEMIO_READ_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_ASO_BLOCK0_PREDICTION_SIZE); |
| BlockType[1] = MEMIO_READ_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_ASO_BLOCK1_PREDICTION_SIZE); |
| BlockType[2] = MEMIO_READ_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_ASO_BLOCK2_PREDICTION_SIZE); |
| BlockType[3] = MEMIO_READ_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_ASO_BLOCK3_PREDICTION_SIZE); |
| |
| /* read motion vectors in all 16 4x4 sub-blocks*/ |
| for (i = 1; i < 3; i++) { /* get blocks 11 and 14 */ |
| Value = MEMIO_READ_TABLE_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_COMP_X_ABOVE, i); |
| REGIO_WRITE_FIELD(MotionVecCmd[CurrentAboveTileMap[i]], MSVDX_CMDS, MOTION_VECTOR, MV_X, Value); |
| Value = MEMIO_READ_TABLE_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_COMP_Y_ABOVE, i); |
| REGIO_WRITE_FIELD(MotionVecCmd[CurrentAboveTileMap[i]], MSVDX_CMDS, MOTION_VECTOR, MV_Y, Value); |
| } |
| for (i = 0; i < 14; i++) { |
| Value = MEMIO_READ_TABLE_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_COMP_X_COL, i); |
| REGIO_WRITE_FIELD(MotionVecCmd[CurrentColTileMap[i]], MSVDX_CMDS, MOTION_VECTOR, MV_X, Value); |
| Value = MEMIO_READ_TABLE_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_COMP_Y_COL, i); |
| REGIO_WRITE_FIELD(MotionVecCmd[CurrentColTileMap[i]], MSVDX_CMDS, MOTION_VECTOR, MV_Y, Value); |
| } |
| |
| /* read DPB index for all 4 blocks */ |
| for (i = 0; i < 4; i++) { |
| DpbIdx[ColBlockMap[i]] = MEMIO_READ_TABLE_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_DPB_IDX_COL, i); |
| } |
| |
| /* Send commands required blocks */ |
| for (BlockNum = 0; |
| BlockNum < BlocksToSendMap[BlockType[0]]; |
| BlockNum++) { |
| /* block address */ |
| Block8x8 = BlockAddressMap[BlockType[0]][BlockNum]; |
| /* block type */ |
| blockType = BlockType[Block8x8]; |
| |
| InterBlockCmd = 0; |
| REGIO_WRITE_FIELD(InterBlockCmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, INTER_PRED_BLOCK_SIZE, blockType); |
| REGIO_WRITE_FIELD(InterBlockCmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_A_VALID, 1); |
| REGIO_WRITE_FIELD(InterBlockCmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_A, DpbIdx[Block8x8]); |
| |
| /* send commands */ |
| h264_pollForSpaceForNCommands(1 + VectorsToSendMap[blockType]); |
| psb_deblock_reg_table_set(MSVDX_CMDS, INTER_BLOCK_PREDICTION, Block8x8, InterBlockCmd); |
| |
| for (i = 0; i < VectorsToSendMap[blockType]; i++) { |
| /* only send forward MVs in baseline */ |
| MvAddr = (2 * 4 * Block8x8) + VectorOffsetMap[blockType][i]; |
| Mv = (4 * Block8x8) + VectorOffsetMap[blockType][i]; |
| psb_deblock_reg_table_set(MSVDX_CMDS, MOTION_VECTOR, MvAddr, MotionVecCmd[Mv]); |
| } |
| } |
| } |
| |
| void |
| h264_currentIntraBlockPrediction(psb_cmdbuf_p cmdbuf, uint8_t * MbData, int bMbIsIPCM) |
| { |
| uint32_t BlockSizeY, BlockSizeC; |
| uint32_t IntraCmdY, IntraCmdC; |
| |
| /* select block size I_PCM or I_16x16 */ |
| BlockSizeY = (1 == bMbIsIPCM) ? 3 : 0; |
| /* select block size I_PCM or I_8x8 */ |
| BlockSizeC = (1 == bMbIsIPCM) ? 3 : 1; |
| |
| IntraCmdY = IntraCmdC = 0; |
| |
| REGIO_WRITE_FIELD( |
| IntraCmdY, |
| MSVDX_CMDS, INTRA_BLOCK_PREDICTION, |
| INTRA_PRED_BLOCK_SIZE, |
| BlockSizeY); |
| REGIO_WRITE_FIELD( |
| IntraCmdC, |
| MSVDX_CMDS, INTRA_BLOCK_PREDICTION, |
| INTRA_PRED_BLOCK_SIZE, |
| BlockSizeC); |
| |
| h264_pollForSpaceForNCommands(2); |
| psb_deblock_reg_table_set(MSVDX_CMDS, INTRA_BLOCK_PREDICTION, 0, IntraCmdY); |
| psb_deblock_reg_table_set(MSVDX_CMDS, INTRA_BLOCK_PREDICTION, 4, IntraCmdC); |
| } |
| |
| void |
| h264_above1IntraBlockPrediction(psb_cmdbuf_p cmdbuf, uint8_t * MbData, int bMbIsIPCM) |
| { |
| uint32_t BlockSizeY; |
| uint32_t IntraCmdY; |
| |
| /* select block size I_PCM or I_16x16 */ |
| BlockSizeY = (1 == bMbIsIPCM) ? 3 : 0; |
| IntraCmdY = 0; |
| |
| REGIO_WRITE_FIELD( |
| IntraCmdY, |
| MSVDX_CMDS, INTRA_BLOCK_PREDICTION_ABOVE1, |
| INTRA_PRED_BLOCK_SIZE_ABOVE1, |
| BlockSizeY); |
| |
| h264_pollForSpaceForNCommands(1); |
| psb_deblock_reg_table_set(MSVDX_CMDS, INTRA_BLOCK_PREDICTION_ABOVE1, 0, IntraCmdY); |
| } |
| |
| void |
| h264_macroblockCmdSequence(psb_cmdbuf_p cmdbuf, uint8_t * MbData, uint32_t X, uint32_t Y, int bCurrent) |
| { |
| int bMbIsIPCM; |
| uint32_t MbType; |
| uint32_t Value; |
| uint32_t MbNumberCmd, MbQuantCmd, MbTransZeroCmd; |
| |
| /* Macroblock Type */ |
| MbType = MEMIO_READ_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_MBTYPE); |
| |
| /* Macroblock Number */ |
| /* no need for MB_ERROR_FLAG as error info is not stored */ |
| /* no need for MB_FIELD_CODE as basline is always frame based */ |
| MbNumberCmd = 0; |
| |
| Value = (3 == MbType) ? 0 : MbType; |
| REGIO_WRITE_FIELD(MbNumberCmd, MSVDX_CMDS, MACROBLOCK_NUMBER, MB_CODE_TYPE, Value); |
| |
| REGIO_WRITE_FIELD(MbNumberCmd, MSVDX_CMDS, MACROBLOCK_NUMBER, MB_NO_Y, Y); |
| REGIO_WRITE_FIELD(MbNumberCmd, MSVDX_CMDS, MACROBLOCK_NUMBER, MB_NO_X, X); |
| |
| /* H264 Quant */ |
| /* TRANSFORM_SIZE_8X8 always false in basline */ |
| MbQuantCmd = 0; |
| |
| Value = MEMIO_READ_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_QP_CR); |
| REGIO_WRITE_FIELD(MbQuantCmd, MSVDX_CMDS, MACROBLOCK_H264_QUANT, MB_QUANT_CHROMA_CR, Value); |
| |
| Value = MEMIO_READ_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_QP_CB); |
| REGIO_WRITE_FIELD(MbQuantCmd, MSVDX_CMDS, MACROBLOCK_H264_QUANT, MB_QUANT_CHROMA_CB, Value); |
| |
| Value = MEMIO_READ_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_QP); |
| REGIO_WRITE_FIELD(MbQuantCmd, MSVDX_CMDS, MACROBLOCK_H264_QUANT, MB_QUANT_LUMA, Value); |
| |
| /* send 2 commands */ |
| h264_pollForSpaceForNCommands(2); |
| if (1 == bCurrent) { |
| /* Top and Left available flags are only sent for current MB */ |
| Value = MEMIO_READ_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_MB_AVAILABLE_TOP_FLAG); |
| Value = (1 == Value) ? 0 : 1; |
| REGIO_WRITE_FIELD(MbNumberCmd, MSVDX_CMDS, MACROBLOCK_NUMBER, MB_SLICE_TOP, Value); |
| |
| Value = MEMIO_READ_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_MB_AVAILABLE_LEFT_FLAG); |
| Value = (1 == Value) ? 0 : 1; |
| REGIO_WRITE_FIELD(MbNumberCmd, MSVDX_CMDS, MACROBLOCK_NUMBER, MB_SLICE_LHS, Value); |
| |
| psb_deblock_reg_set(MSVDX_CMDS, MACROBLOCK_NUMBER, MbNumberCmd); |
| psb_deblock_reg_set(MSVDX_CMDS, MACROBLOCK_H264_QUANT, MbQuantCmd); |
| } else { |
| psb_deblock_reg_set(MSVDX_CMDS, MACROBLOCK_NUMBER_ABOVE1, MbNumberCmd); |
| psb_deblock_reg_set(MSVDX_CMDS, MACROBLOCK_H264_QUANT_ABOVE1, MbQuantCmd); |
| } |
| |
| /* Prediction Block Sequence */ |
| bMbIsIPCM = 0; |
| switch (MbType) { |
| case 3: /* IPCM */ |
| bMbIsIPCM = 1; |
| /* deliberate drop through */ |
| case 0: /* I */ |
| if (1 == bCurrent) { |
| h264_currentIntraBlockPrediction(cmdbuf, MbData, bMbIsIPCM); |
| } else { |
| h264_above1IntraBlockPrediction(cmdbuf, MbData, bMbIsIPCM); |
| } |
| break; |
| case 1: /* P */ |
| if (1 == bCurrent) { |
| h264_currentInterBlockSequence(cmdbuf, MbData); |
| } else { |
| h264_above1InterBlockSequence(cmdbuf, MbData); |
| } |
| break; |
| case 2: /* B */ |
| default: |
| /* invalid MB type */ |
| //IMG_ASSERT( 0 ); |
| break; |
| } |
| |
| /* Trasform Zero */ |
| MbTransZeroCmd = 0; |
| Value = MEMIO_READ_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_ASO_MB_TRANSFORM_ZERO); |
| REGIO_WRITE_FIELD(MbTransZeroCmd, MSVDX_CMDS, MACROBLOCK_BLOCK_TRANSFORM_ZERO, MB_BLOCK_TRANSFORM_ZERO, Value); |
| |
| /* write last command */ |
| h264_pollForSpaceForNCommands(1); |
| if (1 == bCurrent) { |
| psb_deblock_reg_set(MSVDX_CMDS, MACROBLOCK_BLOCK_TRANSFORM_ZERO, MbTransZeroCmd); |
| } else { |
| MbTransZeroCmd &= 0x0000CC00; /* only send for sub-blocks 10,11,14 and 15 */ |
| psb_deblock_reg_set(MSVDX_CMDS, MACROBLOCK_BLOCK_TRANSFORM_ZERO_ABOVE1, MbTransZeroCmd); |
| } |
| } |
| |
| uint32_t |
| h264_getCurrentSliceCmd(uint8_t* MbData) |
| { |
| uint32_t Value, Cmd; |
| |
| Cmd = 0; |
| |
| /* unpack data from stored MB + repack in command */ |
| Value = MEMIO_READ_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_COPY_DISABLE_DEBLOCK_FILTER_IDC); |
| REGIO_WRITE_FIELD(Cmd, MSVDX_CMDS, SLICE_PARAMS, DISABLE_DEBLOCK_FILTER_IDC, Value); |
| |
| Value = MEMIO_READ_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_COPY_H264_BE_SLICE0_ALPHA_CO_OFFSET_DIV2); |
| REGIO_WRITE_FIELD(Cmd, MSVDX_CMDS, SLICE_PARAMS, SLICE_ALPHA_CO_OFFSET_DIV2, Value); |
| |
| Value = MEMIO_READ_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_COPY_H264_BE_SLICE0_BETA_OFFSET_DIV2); |
| REGIO_WRITE_FIELD(Cmd, MSVDX_CMDS, SLICE_PARAMS, SLICE_BETA_OFFSET_DIV2, Value); |
| |
| Value = MEMIO_READ_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_COPY_H264_BE_SLICE0_FIELD_TYPE); |
| REGIO_WRITE_FIELD(Cmd, MSVDX_CMDS, SLICE_PARAMS, SLICE_FIELD_TYPE, Value); |
| |
| Value = MEMIO_READ_FIELD(MbData, MSVDX_VEC_ENTDEC_VLRIF_H264_MB_UNIT_COPY_H264_BE_SLICE0_CODE_TYPE); |
| REGIO_WRITE_FIELD(Cmd, MSVDX_CMDS, SLICE_PARAMS, SLICE_CODE_TYPE, Value); |
| |
| return Cmd; |
| } |
| |
| int h264_secondPass( |
| psb_cmdbuf_p cmdbuf, |
| uint8_t * MbData, |
| uint32_t OperatingModeCmd, |
| uint32_t Width, |
| uint32_t Height |
| ) |
| { |
| uint32_t i, PicSize; |
| uint32_t EndOfPictureCmd; |
| uint32_t EndOfSliceCmd; |
| uint32_t SliceCmd, OldSliceCmd; |
| uint32_t EnableReg; |
| uint8_t * CurrMb; |
| uint8_t * Above1Mb; |
| int bRetCode = 0; |
| |
| PicSize = Width * Height; |
| |
| /* End of Slice command */ |
| EndOfSliceCmd = 0; |
| REGIO_WRITE_FIELD(EndOfSliceCmd, MSVDX_CMDS, END_SLICE_PICTURE, PICTURE_END, 0); |
| |
| |
| /* put vdeb into second pass mode */ |
| /* send operating mode command for VDEB only */ |
| REGIO_WRITE_FIELD(OperatingModeCmd, MSVDX_CMDS, OPERATING_MODE, ASYNC_MODE, 2); /* VDEB only */ |
| h264_pollForSpaceForNCommands(1); |
| psb_deblock_reg_get(MSVDX_CORE, CR_MSVDX_COMMAND_SPACE); |
| psb_deblock_reg_set(MSVDX_CMDS, OPERATING_MODE, OperatingModeCmd); |
| |
| PollForSpaceForXCommands; |
| |
| /* Send Slice Command */ |
| SliceCmd = h264_getCurrentSliceCmd(MbData); |
| h264_pollForSpaceForNCommands(2); |
| psb_deblock_reg_set(MSVDX_CMDS, SLICE_PARAMS, SliceCmd); |
| psb_deblock_reg_set(MSVDX_CMDS, SLICE_PARAMS_ABOVE1, SliceCmd); |
| /* process top row */ |
| for (i = 0, CurrMb = MbData; |
| i < Width; |
| i++, CurrMb += H264_MACROBLOCK_DATA_SIZE) { |
| OldSliceCmd = SliceCmd; |
| SliceCmd = h264_getCurrentSliceCmd(CurrMb); |
| if (OldSliceCmd != SliceCmd) { |
| h264_pollForSpaceForNCommands(2); |
| psb_deblock_reg_set(MSVDX_CMDS, END_SLICE_PICTURE, EndOfSliceCmd); |
| psb_deblock_reg_set(MSVDX_CMDS, SLICE_PARAMS, SliceCmd); |
| } |
| |
| h264_macroblockCmdSequence(cmdbuf, CurrMb, i, 0, 1); |
| } |
| |
| /* process rest of picture */ |
| for (Above1Mb = MbData; |
| i < PicSize; |
| i++, CurrMb += H264_MACROBLOCK_DATA_SIZE, Above1Mb += H264_MACROBLOCK_DATA_SIZE) { |
| OldSliceCmd = SliceCmd; |
| SliceCmd = h264_getCurrentSliceCmd(CurrMb); |
| if (OldSliceCmd != SliceCmd) { |
| h264_pollForSpaceForNCommands(2); |
| psb_deblock_reg_set(MSVDX_CMDS, END_SLICE_PICTURE, EndOfSliceCmd); |
| psb_deblock_reg_set(MSVDX_CMDS, SLICE_PARAMS, SliceCmd); |
| } |
| |
| h264_macroblockCmdSequence(cmdbuf, Above1Mb, (i % Width), (i / Width) - 1, 0); |
| h264_macroblockCmdSequence(cmdbuf, CurrMb, (i % Width), (i / Width), 1); |
| } |
| |
| /* send end of pic + restart back end */ |
| EndOfPictureCmd = 0; |
| EnableReg = 0; |
| REGIO_WRITE_FIELD(EndOfPictureCmd, MSVDX_CMDS, END_SLICE_PICTURE, PICTURE_END, 1); |
| REGIO_WRITE_FIELD(EnableReg, MSVDX_VEC, CR_VEC_CONTROL, ENTDEC_ENABLE_BE, 1); |
| |
| h264_pollForSpaceForNCommands(2); |
| psb_deblock_reg_set(MSVDX_CMDS, END_SLICE_PICTURE, EndOfSliceCmd); |
| psb_deblock_reg_set(MSVDX_CMDS, END_SLICE_PICTURE, EndOfPictureCmd); |
| //psb_deblock_reg_set( MSVDX_VEC, CR_VEC_CONTROL, EnableReg); /* this is not a command */ |
| return bRetCode; |
| } |
| |
| int psb_cmdbuf_second_pass(object_context_p obj_context, |
| uint32_t OperatingModeCmd, |
| unsigned char * pvParamBase, |
| uint32_t PicWidthInMbs, |
| uint32_t FrameHeightInMbs, |
| psb_buffer_p target_buffer, |
| uint32_t chroma_offset |
| ) |
| { |
| int bRetVal = 1; |
| uint32_t Cmd, item_loc; |
| uint32_t *cmd_size; |
| psb_cmdbuf_p cmdbuf = obj_context->cmdbuf; |
| |
| if (psb_buffer_map(&cmdbuf->regio_buf, &cmdbuf->regio_base)) { |
| //printf("map cmdbuf->regio_buf error\n"); |
| return bRetVal; |
| } |
| |
| item_loc = psb_cmdbuf_buffer_ref(cmdbuf, &cmdbuf->regio_buf); |
| |
| cmdbuf->regio_idx = (uint32_t *)cmdbuf->regio_base; |
| cmd_size = cmdbuf->regio_idx++; |
| |
| h264_pollForSpaceForNCommands(4); |
| |
| psb_deblock_reg_set_RELOC(MSVDX_CMDS, LUMA_RECONSTRUCTED_PICTURE_BASE_ADDRESSES, target_buffer, target_buffer->buffer_ofs, item_loc); |
| psb_deblock_reg_set_RELOC(MSVDX_CMDS, CHROMA_RECONSTRUCTED_PICTURE_BASE_ADDRESSES, target_buffer, target_buffer->buffer_ofs + chroma_offset, item_loc); |
| |
| Cmd = 0; |
| REGIO_WRITE_FIELD_LITE(Cmd, MSVDX_CMDS, DISPLAY_PICTURE_SIZE, DISPLAY_PICTURE_HEIGHT, (FrameHeightInMbs * 16) - 1); |
| REGIO_WRITE_FIELD_LITE(Cmd, MSVDX_CMDS, DISPLAY_PICTURE_SIZE, DISPLAY_PICTURE_WIDTH, (PicWidthInMbs * 16) - 1); |
| psb_deblock_reg_set(MSVDX_CMDS, DISPLAY_PICTURE_SIZE, Cmd); |
| |
| |
| Cmd = 0; |
| REGIO_WRITE_FIELD_LITE(Cmd, MSVDX_CMDS, CODED_PICTURE_SIZE, CODED_PICTURE_HEIGHT, (FrameHeightInMbs * 16) - 1); |
| REGIO_WRITE_FIELD_LITE(Cmd, MSVDX_CMDS, CODED_PICTURE_SIZE, CODED_PICTURE_WIDTH, (PicWidthInMbs * 16) - 1); |
| psb_deblock_reg_set(MSVDX_CMDS, CODED_PICTURE_SIZE, Cmd); |
| |
| /* BRN25312 */ |
| psb_deblock_reg_set(MSVDX_CMDS, VC1_LUMA_RANGE_MAPPING_BASE_ADDRESS, 0); |
| psb_deblock_reg_set(MSVDX_CMDS, VC1_CHROMA_RANGE_MAPPING_BASE_ADDRESS, 0); |
| psb_deblock_reg_set(MSVDX_CMDS, VC1_RANGE_MAPPING_FLAGS, 0); |
| |
| /* process second pass */ |
| bRetVal = h264_secondPass(cmdbuf, |
| (uint8_t*)pvParamBase, |
| OperatingModeCmd, |
| PicWidthInMbs, |
| FrameHeightInMbs); |
| |
| *cmd_size = (cmdbuf->regio_idx - (uint32_t *)cmdbuf->regio_base - 1); |
| |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "DEBLOCK: REGIO size is %d\n", (uint32_t)(cmdbuf->regio_idx - (uint32_t *)cmdbuf->regio_base) - 1); |
| //printf("DEBLOCK: REGIO size is %d\n", (uint32_t)(cmdbuf->regio_idx - (uint32_t *)cmdbuf->regio_base) - 1); |
| psb_buffer_unmap(&cmdbuf->regio_buf); |
| return bRetVal; |
| } |