| /* |
| * drivers/amlogic/amports/vvp9.c |
| * |
| * Copyright (C) 2015 Amlogic, Inc. All rights reserved. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| * more details. |
| * |
| */ |
| #define DEBUG |
| #include <linux/kernel.h> |
| #include <linux/module.h> |
| #include <linux/types.h> |
| #include <linux/errno.h> |
| #include <linux/interrupt.h> |
| #include <linux/semaphore.h> |
| #include <linux/delay.h> |
| #include <linux/timer.h> |
| #include <linux/kfifo.h> |
| #include <linux/kthread.h> |
| #include <linux/spinlock.h> |
| #include <linux/platform_device.h> |
| #include <linux/amlogic/media/vfm/vframe.h> |
| #include <linux/amlogic/media/utils/amstream.h> |
| #include <linux/amlogic/media/utils/vformat.h> |
| #include <linux/amlogic/media/frame_sync/ptsserv.h> |
| #include <linux/amlogic/media/canvas/canvas.h> |
| #include <linux/amlogic/media/vfm/vframe_provider.h> |
| #include <linux/amlogic/media/vfm/vframe_receiver.h> |
| #include <linux/dma-mapping.h> |
| #include <linux/dma-contiguous.h> |
| #include <linux/slab.h> |
| #include <linux/amlogic/tee.h> |
| #include "../../../stream_input/amports/amports_priv.h" |
| #include <linux/amlogic/media/codec_mm/codec_mm.h> |
| #include "../utils/decoder_mmu_box.h" |
| #include "../utils/decoder_bmmu_box.h" |
| |
| #define MEM_NAME "codec_vp9" |
| /* #include <mach/am_regs.h> */ |
| #include <linux/amlogic/media/utils/vdec_reg.h> |
| #include "../utils/vdec.h" |
| #include "../utils/amvdec.h" |
| #ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC |
| #include "../utils/vdec_profile.h" |
| #endif |
| |
| #include <linux/amlogic/media/video_sink/video.h> |
| #include <linux/amlogic/media/codec_mm/configs.h> |
| #include "../utils/config_parser.h" |
| #include "../utils/firmware.h" |
| #include "../../../common/chips/decoder_cpu_ver_info.h" |
| #include "../utils/vdec_v4l2_buffer_ops.h" |
| #include <media/v4l2-mem2mem.h> |
| |
| #define MIX_STREAM_SUPPORT |
| |
| #include "vvp9.h" |
| |
| |
| /*#define SUPPORT_FB_DECODING*/ |
| /*#define FB_DECODING_TEST_SCHEDULE*/ |
| |
| |
| #define HW_MASK_FRONT 0x1 |
| #define HW_MASK_BACK 0x2 |
| |
| #define VP9D_MPP_REFINFO_TBL_ACCCONFIG 0x3442 |
| #define VP9D_MPP_REFINFO_DATA 0x3443 |
| #define VP9D_MPP_REF_SCALE_ENBL 0x3441 |
| #define HEVC_MPRED_CTRL4 0x324c |
| #define HEVC_CM_HEADER_START_ADDR 0x3628 |
| #define HEVC_DBLK_CFGB 0x350b |
| #define HEVCD_MPP_ANC2AXI_TBL_DATA 0x3464 |
| #define HEVC_SAO_MMU_VH1_ADDR 0x363b |
| #define HEVC_SAO_MMU_VH0_ADDR 0x363a |
| |
| #define HEVC_MV_INFO 0x310d |
| #define HEVC_QP_INFO 0x3137 |
| #define HEVC_SKIP_INFO 0x3136 |
| |
| #define VP9_10B_DEC_IDLE 0 |
| #define VP9_10B_DEC_FRAME_HEADER 1 |
| #define VP9_10B_DEC_SLICE_SEGMENT 2 |
| #define VP9_10B_DECODE_SLICE 5 |
| #define VP9_10B_DISCARD_NAL 6 |
| #define VP9_DUMP_LMEM 7 |
| #define HEVC_DECPIC_DATA_DONE 0xa |
| #define HEVC_DECPIC_DATA_ERROR 0xb |
| #define HEVC_NAL_DECODE_DONE 0xe |
| #define HEVC_DECODE_BUFEMPTY 0x20 |
| #define HEVC_DECODE_TIMEOUT 0x21 |
| #define HEVC_SEARCH_BUFEMPTY 0x22 |
| #define HEVC_DECODE_OVER_SIZE 0x23 |
| #define HEVC_S2_DECODING_DONE 0x50 |
| #define VP9_HEAD_PARSER_DONE 0xf0 |
| #define VP9_HEAD_SEARCH_DONE 0xf1 |
| #define VP9_EOS 0xf2 |
| #define HEVC_ACTION_DONE 0xff |
| |
| #define VF_POOL_SIZE 32 |
| |
| #undef pr_info |
| #define pr_info printk |
| |
| #define DECODE_MODE_SINGLE ((0x80 << 24) | 0) |
| #define DECODE_MODE_MULTI_STREAMBASE ((0x80 << 24) | 1) |
| #define DECODE_MODE_MULTI_FRAMEBASE ((0x80 << 24) | 2) |
| #define DECODE_MODE_SINGLE_LOW_LATENCY ((0x80 << 24) | 3) |
| #define DECODE_MODE_MULTI_FRAMEBASE_NOHEAD ((0x80 << 24) | 4) |
| |
| #define VP9_TRIGGER_FRAME_DONE 0x100 |
| #define VP9_TRIGGER_FRAME_ENABLE 0x200 |
| |
| #define MV_MEM_UNIT 0x240 |
| /*--------------------------------------------------- |
| * Include "parser_cmd.h" |
| *--------------------------------------------------- |
| */ |
| #define PARSER_CMD_SKIP_CFG_0 0x0000090b |
| |
| #define PARSER_CMD_SKIP_CFG_1 0x1b14140f |
| |
| #define PARSER_CMD_SKIP_CFG_2 0x001b1910 |
| |
| #define PARSER_CMD_NUMBER 37 |
| |
| /*#define HEVC_PIC_STRUCT_SUPPORT*/ |
| /* to remove, fix build error */ |
| |
| /*#define CODEC_MM_FLAGS_FOR_VDECODER 0*/ |
| |
| #define MULTI_INSTANCE_SUPPORT |
| #define SUPPORT_10BIT |
| /* #define ERROR_HANDLE_DEBUG */ |
| |
| #ifndef STAT_KTHREAD |
| #define STAT_KTHREAD 0x40 |
| #endif |
| |
| #ifdef MULTI_INSTANCE_SUPPORT |
| #define MAX_DECODE_INSTANCE_NUM 9 |
| #define MULTI_DRIVER_NAME "ammvdec_vp9" |
| static unsigned int max_decode_instance_num |
| = MAX_DECODE_INSTANCE_NUM; |
| static unsigned int decode_frame_count[MAX_DECODE_INSTANCE_NUM]; |
| static unsigned int display_frame_count[MAX_DECODE_INSTANCE_NUM]; |
| static unsigned int max_process_time[MAX_DECODE_INSTANCE_NUM]; |
| static unsigned int run_count[MAX_DECODE_INSTANCE_NUM]; |
| static unsigned int input_empty[MAX_DECODE_INSTANCE_NUM]; |
| static unsigned int not_run_ready[MAX_DECODE_INSTANCE_NUM]; |
| |
| static u32 decode_timeout_val = 200; |
| static int start_decode_buf_level = 0x8000; |
| static u32 work_buf_size; |
| |
| static u32 force_pts_unstable; |
| |
| static u32 mv_buf_margin; |
| |
| static u32 mv_buf_dynamic_alloc; |
| |
| /* DOUBLE_WRITE_MODE is enabled only when NV21 8 bit output is needed */ |
| /* double_write_mode: |
| * 0, no double write; |
| * 1, 1:1 ratio; |
| * 2, (1/4):(1/4) ratio; |
| * 3, (1/4):(1/4) ratio, with both compressed frame included |
| * 4, (1/2):(1/2) ratio; |
| * 0x10, double write only |
| * 0x100, if > 1080p,use mode 4,else use mode 1; |
| * 0x200, if > 1080p,use mode 2,else use mode 1; |
| * 0x300, if > 720p, use mode 4, else use mode 1; |
| */ |
| static u32 double_write_mode; |
| |
| #define DRIVER_NAME "amvdec_vp9" |
| #define DRIVER_HEADER_NAME "amvdec_vp9_header" |
| |
| |
| #define PUT_INTERVAL (HZ/100) |
| #define ERROR_SYSTEM_RESET_COUNT 200 |
| |
| #define PTS_NORMAL 0 |
| #define PTS_NONE_REF_USE_DURATION 1 |
| |
| #define PTS_MODE_SWITCHING_THRESHOLD 3 |
| #define PTS_MODE_SWITCHING_RECOVERY_THREASHOLD 3 |
| |
| #define DUR2PTS(x) ((x)*90/96) |
| |
| struct VP9Decoder_s; |
| static int vvp9_vf_states(struct vframe_states *states, void *); |
| static struct vframe_s *vvp9_vf_peek(void *); |
| static struct vframe_s *vvp9_vf_get(void *); |
| static void vvp9_vf_put(struct vframe_s *, void *); |
| static int vvp9_event_cb(int type, void *data, void *private_data); |
| |
| static int vvp9_stop(struct VP9Decoder_s *pbi); |
| #ifdef MULTI_INSTANCE_SUPPORT |
| static s32 vvp9_init(struct vdec_s *vdec); |
| #else |
| static s32 vvp9_init(struct VP9Decoder_s *pbi); |
| #endif |
| static void vvp9_prot_init(struct VP9Decoder_s *pbi, u32 mask); |
| static int vvp9_local_init(struct VP9Decoder_s *pbi); |
| static void vvp9_put_timer_func(unsigned long arg); |
| static void dump_data(struct VP9Decoder_s *pbi, int size); |
| static unsigned char get_data_check_sum |
| (struct VP9Decoder_s *pbi, int size); |
| static void dump_pic_list(struct VP9Decoder_s *pbi); |
| static int vp9_alloc_mmu( |
| struct VP9Decoder_s *pbi, |
| int cur_buf_idx, |
| int pic_width, |
| int pic_height, |
| unsigned short bit_depth, |
| unsigned int *mmu_index_adr); |
| |
| |
| static const char vvp9_dec_id[] = "vvp9-dev"; |
| |
| #define PROVIDER_NAME "decoder.vp9" |
| #define MULTI_INSTANCE_PROVIDER_NAME "vdec.vp9" |
| |
| static const struct vframe_operations_s vvp9_vf_provider = { |
| .peek = vvp9_vf_peek, |
| .get = vvp9_vf_get, |
| .put = vvp9_vf_put, |
| .event_cb = vvp9_event_cb, |
| .vf_states = vvp9_vf_states, |
| }; |
| |
| static struct vframe_provider_s vvp9_vf_prov; |
| |
| static u32 bit_depth_luma; |
| static u32 bit_depth_chroma; |
| static u32 frame_width; |
| static u32 frame_height; |
| static u32 video_signal_type; |
| |
| static u32 on_no_keyframe_skiped; |
| |
| #define PROB_SIZE (496 * 2 * 4) |
| #define PROB_BUF_SIZE (0x5000) |
| #define COUNT_BUF_SIZE (0x300 * 4 * 4) |
| /*compute_losless_comp_body_size(4096, 2304, 1) = 18874368(0x1200000)*/ |
| #define MAX_FRAME_4K_NUM 0x1200 |
| #define MAX_FRAME_8K_NUM 0x4800 |
| |
| #define HEVC_ASSIST_MMU_MAP_ADDR 0x3009 |
| |
| #ifdef SUPPORT_FB_DECODING |
| /* register define */ |
| #define HEVC_ASSIST_HED_FB_W_CTL 0x3006 |
| #define HEVC_ASSIST_HED_FB_R_CTL 0x3007 |
| #define HEVC_ASSIST_HED_FB_ADDR 0x3008 |
| #define HEVC_ASSIST_FB_MMU_MAP_ADDR 0x300a |
| #define HEVC_ASSIST_FBD_MMU_MAP_ADDR 0x300b |
| |
| |
| #define MAX_STAGE_PAGE_NUM 0x1200 |
| #define STAGE_MMU_MAP_SIZE (MAX_STAGE_PAGE_NUM * 4) |
| #endif |
| static inline int div_r32(int64_t m, int n) |
| { |
| /* |
| *return (int)(m/n) |
| */ |
| #ifndef CONFIG_ARM64 |
| int64_t qu = 0; |
| qu = div_s64(m, n); |
| return (int)qu; |
| #else |
| return (int)(m/n); |
| #endif |
| } |
| |
| /*USE_BUF_BLOCK*/ |
| struct BUF_s { |
| int index; |
| unsigned int alloc_flag; |
| /*buffer */ |
| unsigned int cma_page_count; |
| unsigned long alloc_addr; |
| unsigned long start_adr; |
| unsigned int size; |
| |
| unsigned int free_start_adr; |
| ulong v4l_ref_buf_addr; |
| ulong header_addr; |
| u32 header_size; |
| u32 luma_size; |
| ulong chroma_addr; |
| u32 chroma_size; |
| } /*BUF_t */; |
| |
| struct MVBUF_s { |
| unsigned long start_adr; |
| unsigned int size; |
| int used_flag; |
| } /*MVBUF_t */; |
| |
| /* #undef BUFMGR_ONLY to enable hardware configuration */ |
| |
| /*#define TEST_WR_PTR_INC*/ |
| /*#define WR_PTR_INC_NUM 128*/ |
| #define WR_PTR_INC_NUM 1 |
| |
| #define SIMULATION |
| #define DOS_PROJECT |
| #undef MEMORY_MAP_IN_REAL_CHIP |
| |
| /*#undef DOS_PROJECT*/ |
| /*#define MEMORY_MAP_IN_REAL_CHIP*/ |
| |
| /*#define BUFFER_MGR_ONLY*/ |
| /*#define CONFIG_HEVC_CLK_FORCED_ON*/ |
| /*#define ENABLE_SWAP_TEST*/ |
| #define MCRCC_ENABLE |
| |
| #define VP9_LPF_LVL_UPDATE |
| /*#define DBG_LF_PRINT*/ |
| |
| #ifdef VP9_10B_NV21 |
| #else |
| #define LOSLESS_COMPRESS_MODE |
| #endif |
| |
| #define DOUBLE_WRITE_YSTART_TEMP 0x02000000 |
| #define DOUBLE_WRITE_CSTART_TEMP 0x02900000 |
| |
| |
| |
| typedef unsigned int u32; |
| typedef unsigned short u16; |
| |
| #define VP9_DEBUG_BUFMGR 0x01 |
| #define VP9_DEBUG_BUFMGR_MORE 0x02 |
| #define VP9_DEBUG_BUFMGR_DETAIL 0x04 |
| #define VP9_DEBUG_OUT_PTS 0x10 |
| #define VP9_DEBUG_SEND_PARAM_WITH_REG 0x100 |
| #define VP9_DEBUG_MERGE 0x200 |
| #define VP9_DEBUG_DBG_LF_PRINT 0x400 |
| #define VP9_DEBUG_REG 0x800 |
| #define VP9_DEBUG_2_STAGE 0x1000 |
| #define VP9_DEBUG_2_STAGE_MORE 0x2000 |
| #define VP9_DEBUG_QOS_INFO 0x4000 |
| #define VP9_DEBUG_DIS_LOC_ERROR_PROC 0x10000 |
| #define VP9_DEBUG_DIS_SYS_ERROR_PROC 0x20000 |
| #define VP9_DEBUG_DUMP_PIC_LIST 0x40000 |
| #define VP9_DEBUG_TRIG_SLICE_SEGMENT_PROC 0x80000 |
| #define VP9_DEBUG_NO_TRIGGER_FRAME 0x100000 |
| #define VP9_DEBUG_LOAD_UCODE_FROM_FILE 0x200000 |
| #define VP9_DEBUG_FORCE_SEND_AGAIN 0x400000 |
| #define VP9_DEBUG_DUMP_DATA 0x800000 |
| #define VP9_DEBUG_CACHE 0x1000000 |
| #define VP9_DEBUG_CACHE_HIT_RATE 0x2000000 |
| #define IGNORE_PARAM_FROM_CONFIG 0x8000000 |
| #ifdef MULTI_INSTANCE_SUPPORT |
| #define PRINT_FLAG_ERROR 0x0 |
| #define PRINT_FLAG_V4L_DETAIL 0x10000000 |
| #define PRINT_FLAG_VDEC_STATUS 0x20000000 |
| #define PRINT_FLAG_VDEC_DETAIL 0x40000000 |
| #define PRINT_FLAG_VDEC_DATA 0x80000000 |
| #endif |
| static u32 force_bufspec; |
| static u32 debug; |
| static bool is_reset; |
| /*for debug*/ |
| /* |
| udebug_flag: |
| bit 0, enable ucode print |
| bit 1, enable ucode detail print |
| bit [31:16] not 0, pos to dump lmem |
| bit 2, pop bits to lmem |
| bit [11:8], pre-pop bits for alignment (when bit 2 is 1) |
| */ |
| static u32 udebug_flag; |
| /* |
| when udebug_flag[1:0] is not 0 |
| udebug_pause_pos not 0, |
| pause position |
| */ |
| static u32 udebug_pause_pos; |
| /* |
| when udebug_flag[1:0] is not 0 |
| and udebug_pause_pos is not 0, |
| pause only when DEBUG_REG2 is equal to this val |
| */ |
| static u32 udebug_pause_val; |
| |
| static u32 udebug_pause_decode_idx; |
| |
| static u32 without_display_mode; |
| |
| /* |
| *[3:0] 0: default use config from omx. |
| * 1: force enable fence. |
| * 2: disable fence. |
| *[7:4] 0: fence use for driver. |
| * 1: fence fd use for app. |
| */ |
| static u32 force_config_fence; |
| |
| #define DEBUG_REG |
| #ifdef DEBUG_REG |
| void WRITE_VREG_DBG2(unsigned int adr, unsigned int val) |
| { |
| if (debug & VP9_DEBUG_REG) |
| pr_info("%s(%x, %x)\n", __func__, adr, val); |
| if (adr != 0) |
| WRITE_VREG(adr, val); |
| } |
| |
| #undef WRITE_VREG |
| #define WRITE_VREG WRITE_VREG_DBG2 |
| #endif |
| |
| #define FRAME_CNT_WINDOW_SIZE 59 |
| #define RATE_CORRECTION_THRESHOLD 5 |
| /************************************************** |
| |
| VP9 buffer management start |
| |
| ***************************************************/ |
| #define MMU_COMPRESS_HEADER_SIZE_1080P 0x10000 |
| #define MMU_COMPRESS_HEADER_SIZE_4K 0x48000 |
| #define MMU_COMPRESS_HEADER_SIZE_8K 0x120000 |
| |
| |
| //#define MMU_COMPRESS_HEADER_SIZE 0x48000 |
| //#define MMU_COMPRESS_HEADER_SIZE_DW 0x48000 |
| //#define MMU_COMPRESS_8K_HEADER_SIZE (MMU_COMPRESS_HEADER_SIZE * 4) |
| |
| #define MMU_COMPRESS_HEADER_SIZE 0x48000 |
| #define MMU_COMPRESS_8K_HEADER_SIZE (0x48000*4) |
| #define MAX_SIZE_8K (8192 * 4608) |
| #define MAX_SIZE_4K (4096 * 2304) |
| #define IS_8K_SIZE(w, h) (((w) * (h)) > MAX_SIZE_4K) |
| #define IS_4K_SIZE(w, h) (((w) * (h)) > (1920*1088)) |
| |
| #define INVALID_IDX -1 /* Invalid buffer index.*/ |
| |
| #define RPM_BEGIN 0x200 |
| #define RPM_END 0x280 |
| |
| union param_u { |
| struct { |
| unsigned short data[RPM_END - RPM_BEGIN]; |
| } l; |
| struct { |
| /* from ucode lmem, do not change this struct */ |
| unsigned short profile; |
| unsigned short show_existing_frame; |
| unsigned short frame_to_show_idx; |
| unsigned short frame_type; /*1 bit*/ |
| unsigned short show_frame; /*1 bit*/ |
| unsigned short error_resilient_mode; /*1 bit*/ |
| unsigned short intra_only; /*1 bit*/ |
| unsigned short display_size_present; /*1 bit*/ |
| unsigned short reset_frame_context; |
| unsigned short refresh_frame_flags; |
| unsigned short width; |
| unsigned short height; |
| unsigned short display_width; |
| unsigned short display_height; |
| /* |
| *bit[11:8] - ref_frame_info_0 (ref(3-bits), ref_frame_sign_bias(1-bit)) |
| *bit[7:4] - ref_frame_info_1 (ref(3-bits), ref_frame_sign_bias(1-bit)) |
| *bit[3:0] - ref_frame_info_2 (ref(3-bits), ref_frame_sign_bias(1-bit)) |
| */ |
| unsigned short ref_info; |
| /* |
| *bit[2]: same_frame_size0 |
| *bit[1]: same_frame_size1 |
| *bit[0]: same_frame_size2 |
| */ |
| unsigned short same_frame_size; |
| |
| unsigned short mode_ref_delta_enabled; |
| unsigned short ref_deltas[4]; |
| unsigned short mode_deltas[2]; |
| unsigned short filter_level; |
| unsigned short sharpness_level; |
| unsigned short bit_depth; |
| unsigned short seg_quant_info[8]; |
| unsigned short seg_enabled; |
| unsigned short seg_abs_delta; |
| /* bit 15: feature enabled; bit 8, sign; bit[5:0], data */ |
| unsigned short seg_lf_info[8]; |
| } p; |
| }; |
| |
| |
| struct vpx_codec_frame_buffer_s { |
| uint8_t *data; /**< Pointer to the data buffer */ |
| size_t size; /**< Size of data in bytes */ |
| void *priv; /**< Frame's private data */ |
| }; |
| |
| enum vpx_color_space_t { |
| VPX_CS_UNKNOWN = 0, /**< Unknown */ |
| VPX_CS_BT_601 = 1, /**< BT.601 */ |
| VPX_CS_BT_709 = 2, /**< BT.709 */ |
| VPX_CS_SMPTE_170 = 3, /**< SMPTE.170 */ |
| VPX_CS_SMPTE_240 = 4, /**< SMPTE.240 */ |
| VPX_CS_BT_2020 = 5, /**< BT.2020 */ |
| VPX_CS_RESERVED = 6, /**< Reserved */ |
| VPX_CS_SRGB = 7 /**< sRGB */ |
| }; /**< alias for enum vpx_color_space */ |
| |
| enum vpx_bit_depth_t { |
| VPX_BITS_8 = 8, /**< 8 bits */ |
| VPX_BITS_10 = 10, /**< 10 bits */ |
| VPX_BITS_12 = 12, /**< 12 bits */ |
| }; |
| |
| #define MAX_SLICE_NUM 1024 |
| struct PIC_BUFFER_CONFIG_s { |
| int index; |
| int BUF_index; |
| int mv_buf_index; |
| int comp_body_size; |
| int buf_size; |
| int vf_ref; |
| int y_canvas_index; |
| int uv_canvas_index; |
| #ifdef MULTI_INSTANCE_SUPPORT |
| struct canvas_config_s canvas_config[2]; |
| #endif |
| int decode_idx; |
| int slice_type; |
| int stream_offset; |
| u32 pts; |
| u64 pts64; |
| u64 timestamp; |
| uint8_t error_mark; |
| /**/ |
| int slice_idx; |
| /*buffer*/ |
| unsigned long header_adr; |
| unsigned long mpred_mv_wr_start_addr; |
| int mv_size; |
| /*unsigned long mc_y_adr; |
| *unsigned long mc_u_v_adr; |
| */ |
| unsigned int dw_y_adr; |
| unsigned int dw_u_v_adr; |
| int mc_canvas_y; |
| int mc_canvas_u_v; |
| |
| int lcu_total; |
| /**/ |
| int y_width; |
| int y_height; |
| int y_crop_width; |
| int y_crop_height; |
| int y_stride; |
| |
| int uv_width; |
| int uv_height; |
| int uv_crop_width; |
| int uv_crop_height; |
| int uv_stride; |
| |
| int alpha_width; |
| int alpha_height; |
| int alpha_stride; |
| |
| uint8_t *y_buffer; |
| uint8_t *u_buffer; |
| uint8_t *v_buffer; |
| uint8_t *alpha_buffer; |
| |
| uint8_t *buffer_alloc; |
| int buffer_alloc_sz; |
| int border; |
| int frame_size; |
| int subsampling_x; |
| int subsampling_y; |
| unsigned int bit_depth; |
| enum vpx_color_space_t color_space; |
| |
| int corrupted; |
| int flags; |
| unsigned long cma_alloc_addr; |
| |
| int double_write_mode; |
| |
| /* picture qos infomation*/ |
| int max_qp; |
| int avg_qp; |
| int min_qp; |
| int max_skip; |
| int avg_skip; |
| int min_skip; |
| int max_mv; |
| int min_mv; |
| int avg_mv; |
| |
| u32 hw_decode_time; |
| u32 frame_size2; // For frame base mode |
| bool vframe_bound; |
| |
| /* vdec sync. */ |
| struct fence *fence; |
| |
| /* hdr10 plus data */ |
| u32 hdr10p_data_size; |
| char *hdr10p_data_buf; |
| } PIC_BUFFER_CONFIG; |
| |
| enum BITSTREAM_PROFILE { |
| PROFILE_0, |
| PROFILE_1, |
| PROFILE_2, |
| PROFILE_3, |
| MAX_PROFILES |
| }; |
| |
| enum FRAME_TYPE { |
| KEY_FRAME = 0, |
| INTER_FRAME = 1, |
| FRAME_TYPES, |
| }; |
| |
| enum REFERENCE_MODE { |
| SINGLE_REFERENCE = 0, |
| COMPOUND_REFERENCE = 1, |
| REFERENCE_MODE_SELECT = 2, |
| REFERENCE_MODES = 3, |
| }; |
| |
| #define NONE -1 |
| #define INTRA_FRAME 0 |
| #define LAST_FRAME 1 |
| #define GOLDEN_FRAME 2 |
| #define ALTREF_FRAME 3 |
| #define MAX_REF_FRAMES 4 |
| |
| #define REFS_PER_FRAME 3 |
| |
| #define REF_FRAMES_LOG2 3 |
| #define REF_FRAMES (1 << REF_FRAMES_LOG2) |
| #define REF_FRAMES_4K (6) |
| |
| /*4 scratch frames for the new frames to support a maximum of 4 cores decoding |
| *in parallel, 3 for scaled references on the encoder. |
| *TODO(hkuang): Add ondemand frame buffers instead of hardcoding the number |
| * // of framebuffers. |
| *TODO(jkoleszar): These 3 extra references could probably come from the |
| *normal reference pool. |
| */ |
| #define FRAME_BUFFERS (REF_FRAMES + 16) |
| #define HEADER_FRAME_BUFFERS (FRAME_BUFFERS) |
| #define MAX_BUF_NUM (FRAME_BUFFERS) |
| #define MV_BUFFER_NUM FRAME_BUFFERS |
| #ifdef SUPPORT_FB_DECODING |
| #define STAGE_MAX_BUFFERS 16 |
| #else |
| #define STAGE_MAX_BUFFERS 0 |
| #endif |
| |
| #define FRAME_CONTEXTS_LOG2 2 |
| #define FRAME_CONTEXTS (1 << FRAME_CONTEXTS_LOG2) |
| /*buffer + header buffer + workspace*/ |
| #ifdef MV_USE_FIXED_BUF |
| #define MAX_BMMU_BUFFER_NUM (FRAME_BUFFERS + HEADER_FRAME_BUFFERS + 1) |
| #define VF_BUFFER_IDX(n) (n) |
| #define HEADER_BUFFER_IDX(n) (FRAME_BUFFERS + n) |
| #define WORK_SPACE_BUF_ID (FRAME_BUFFERS + HEADER_FRAME_BUFFERS) |
| #else |
| #define MAX_BMMU_BUFFER_NUM \ |
| (FRAME_BUFFERS + HEADER_FRAME_BUFFERS + MV_BUFFER_NUM + 1) |
| #define VF_BUFFER_IDX(n) (n) |
| #define HEADER_BUFFER_IDX(n) (FRAME_BUFFERS + n) |
| #define MV_BUFFER_IDX(n) (FRAME_BUFFERS + HEADER_FRAME_BUFFERS + n) |
| #define WORK_SPACE_BUF_ID \ |
| (FRAME_BUFFERS + HEADER_FRAME_BUFFERS + MV_BUFFER_NUM) |
| #endif |
| |
| struct RefCntBuffer_s { |
| int ref_count; |
| /*MV_REF *mvs;*/ |
| int mi_rows; |
| int mi_cols; |
| struct vpx_codec_frame_buffer_s raw_frame_buffer; |
| struct PIC_BUFFER_CONFIG_s buf; |
| |
| /*The Following variables will only be used in frame parallel decode. |
| * |
| *frame_worker_owner indicates which FrameWorker owns this buffer. NULL means |
| *that no FrameWorker owns, or is decoding, this buffer. |
| *VP9Worker *frame_worker_owner; |
| * |
| *row and col indicate which position frame has been decoded to in real |
| *pixel unit. They are reset to -1 when decoding begins and set to INT_MAX |
| *when the frame is fully decoded. |
| */ |
| int row; |
| int col; |
| } RefCntBuffer; |
| |
| struct RefBuffer_s { |
| /*TODO(dkovalev): idx is not really required and should be removed, now it |
| *is used in vp9_onyxd_if.c |
| */ |
| int idx; |
| struct PIC_BUFFER_CONFIG_s *buf; |
| /*struct scale_factors sf;*/ |
| } RefBuffer; |
| |
| struct InternalFrameBuffer_s { |
| uint8_t *data; |
| size_t size; |
| int in_use; |
| } InternalFrameBuffer; |
| |
| struct InternalFrameBufferList_s { |
| int num_internal_frame_buffers; |
| struct InternalFrameBuffer_s *int_fb; |
| } InternalFrameBufferList; |
| |
| struct BufferPool_s { |
| /*Protect BufferPool from being accessed by several FrameWorkers at |
| *the same time during frame parallel decode. |
| *TODO(hkuang): Try to use atomic variable instead of locking the whole pool. |
| * |
| *Private data associated with the frame buffer callbacks. |
| *void *cb_priv; |
| * |
| *vpx_get_frame_buffer_cb_fn_t get_fb_cb; |
| *vpx_release_frame_buffer_cb_fn_t release_fb_cb; |
| */ |
| |
| struct RefCntBuffer_s frame_bufs[FRAME_BUFFERS]; |
| |
| /*Frame buffers allocated internally by the codec.*/ |
| struct InternalFrameBufferList_s int_frame_buffers; |
| unsigned long flags; |
| spinlock_t lock; |
| |
| } BufferPool; |
| |
| #define lock_buffer_pool(pool, flags) \ |
| spin_lock_irqsave(&pool->lock, flags) |
| |
| #define unlock_buffer_pool(pool, flags) \ |
| spin_unlock_irqrestore(&pool->lock, flags) |
| |
| struct VP9_Common_s { |
| enum vpx_color_space_t color_space; |
| int width; |
| int height; |
| int display_width; |
| int display_height; |
| int last_width; |
| int last_height; |
| |
| int subsampling_x; |
| int subsampling_y; |
| |
| int use_highbitdepth;/*Marks if we need to use 16bit frame buffers.*/ |
| |
| struct PIC_BUFFER_CONFIG_s *frame_to_show; |
| struct RefCntBuffer_s *prev_frame; |
| |
| /*TODO(hkuang): Combine this with cur_buf in macroblockd.*/ |
| struct RefCntBuffer_s *cur_frame; |
| |
| int ref_frame_map[REF_FRAMES]; /* maps fb_idx to reference slot */ |
| |
| /*Prepare ref_frame_map for the next frame. |
| *Only used in frame parallel decode. |
| */ |
| int next_ref_frame_map[REF_FRAMES]; |
| |
| /* TODO(jkoleszar): could expand active_ref_idx to 4, |
| *with 0 as intra, and roll new_fb_idx into it. |
| */ |
| |
| /*Each frame can reference REFS_PER_FRAME buffers*/ |
| struct RefBuffer_s frame_refs[REFS_PER_FRAME]; |
| |
| int prev_fb_idx; |
| int new_fb_idx; |
| int cur_fb_idx_mmu; |
| /*last frame's frame type for motion search*/ |
| enum FRAME_TYPE last_frame_type; |
| enum FRAME_TYPE frame_type; |
| |
| int show_frame; |
| int last_show_frame; |
| int show_existing_frame; |
| |
| /*Flag signaling that the frame is encoded using only INTRA modes.*/ |
| uint8_t intra_only; |
| uint8_t last_intra_only; |
| |
| int allow_high_precision_mv; |
| |
| /*Flag signaling that the frame context should be reset to default |
| *values. 0 or 1 implies don't reset, 2 reset just the context |
| *specified in the frame header, 3 reset all contexts. |
| */ |
| int reset_frame_context; |
| |
| /*MBs, mb_rows/cols is in 16-pixel units; mi_rows/cols is in |
| * MODE_INFO (8-pixel) units. |
| */ |
| int MBs; |
| int mb_rows, mi_rows; |
| int mb_cols, mi_cols; |
| int mi_stride; |
| |
| /*Whether to use previous frame's motion vectors for prediction.*/ |
| int use_prev_frame_mvs; |
| |
| int refresh_frame_context; /* Two state 0 = NO, 1 = YES */ |
| |
| int ref_frame_sign_bias[MAX_REF_FRAMES]; /* Two state 0, 1 */ |
| |
| /*struct loopfilter lf;*/ |
| /*struct segmentation seg;*/ |
| |
| /*TODO(hkuang):Remove this as it is the same as frame_parallel_decode*/ |
| /* in pbi.*/ |
| int frame_parallel_decode; /* frame-based threading.*/ |
| |
| /*Context probabilities for reference frame prediction*/ |
| /*MV_REFERENCE_FRAME comp_fixed_ref;*/ |
| /*MV_REFERENCE_FRAME comp_var_ref[2];*/ |
| enum REFERENCE_MODE reference_mode; |
| |
| /*FRAME_CONTEXT *fc; */ /* this frame entropy */ |
| /*FRAME_CONTEXT *frame_contexts; */ /*FRAME_CONTEXTS*/ |
| /*unsigned int frame_context_idx; *//* Context to use/update */ |
| /*FRAME_COUNTS counts;*/ |
| |
| unsigned int current_video_frame; |
| enum BITSTREAM_PROFILE profile; |
| |
| enum vpx_bit_depth_t bit_depth; |
| |
| int error_resilient_mode; |
| int frame_parallel_decoding_mode; |
| |
| int byte_alignment; |
| int skip_loop_filter; |
| |
| /*External BufferPool passed from outside.*/ |
| struct BufferPool_s *buffer_pool; |
| |
| int above_context_alloc_cols; |
| |
| }; |
| |
| static void set_canvas(struct VP9Decoder_s *pbi, |
| struct PIC_BUFFER_CONFIG_s *pic_config); |
| static int prepare_display_buf(struct VP9Decoder_s *pbi, |
| struct PIC_BUFFER_CONFIG_s *pic_config); |
| |
| static void fill_frame_info(struct VP9Decoder_s *pbi, |
| struct PIC_BUFFER_CONFIG_s *frame, |
| unsigned int framesize, |
| unsigned int pts); |
| |
| static struct PIC_BUFFER_CONFIG_s *get_frame_new_buffer(struct VP9_Common_s *cm) |
| { |
| return &cm->buffer_pool->frame_bufs[cm->new_fb_idx].buf; |
| } |
| |
| static void ref_cnt_fb(struct RefCntBuffer_s *bufs, int *idx, int new_idx) |
| { |
| const int ref_index = *idx; |
| |
| if (ref_index >= 0 && bufs[ref_index].ref_count > 0) { |
| bufs[ref_index].ref_count--; |
| /*pr_info("[MMU DEBUG 2] dec ref_count[%d] : %d\r\n", |
| * ref_index, bufs[ref_index].ref_count); |
| */ |
| } |
| |
| *idx = new_idx; |
| |
| bufs[new_idx].ref_count++; |
| /*pr_info("[MMU DEBUG 3] inc ref_count[%d] : %d\r\n", |
| * new_idx, bufs[new_idx].ref_count); |
| */ |
| } |
| |
| int vp9_release_frame_buffer(struct vpx_codec_frame_buffer_s *fb) |
| { |
| struct InternalFrameBuffer_s *const int_fb = |
| (struct InternalFrameBuffer_s *)fb->priv; |
| if (int_fb) |
| int_fb->in_use = 0; |
| return 0; |
| } |
| |
| static int compute_losless_comp_body_size(int width, int height, |
| uint8_t is_bit_depth_10); |
| |
| static void setup_display_size(struct VP9_Common_s *cm, union param_u *params, |
| int print_header_info) |
| { |
| cm->display_width = cm->width; |
| cm->display_height = cm->height; |
| if (params->p.display_size_present) { |
| if (print_header_info) |
| pr_info(" * 1-bit display_size_present read : 1\n"); |
| cm->display_width = params->p.display_width; |
| cm->display_height = params->p.display_height; |
| /*vp9_read_frame_size(rb, &cm->display_width, |
| * &cm->display_height); |
| */ |
| } else { |
| if (print_header_info) |
| pr_info(" * 1-bit display_size_present read : 0\n"); |
| } |
| } |
| |
| |
| uint8_t print_header_info = 0; |
| |
| struct buff_s { |
| u32 buf_start; |
| u32 buf_size; |
| u32 buf_end; |
| } buff_t; |
| |
| struct BuffInfo_s { |
| u32 max_width; |
| u32 max_height; |
| u32 start_adr; |
| u32 end_adr; |
| struct buff_s ipp; |
| struct buff_s sao_abv; |
| struct buff_s sao_vb; |
| struct buff_s short_term_rps; |
| struct buff_s vps; |
| struct buff_s sps; |
| struct buff_s pps; |
| struct buff_s sao_up; |
| struct buff_s swap_buf; |
| struct buff_s swap_buf2; |
| struct buff_s scalelut; |
| struct buff_s dblk_para; |
| struct buff_s dblk_data; |
| struct buff_s seg_map; |
| struct buff_s mmu_vbh; |
| struct buff_s cm_header; |
| struct buff_s mpred_above; |
| #ifdef MV_USE_FIXED_BUF |
| struct buff_s mpred_mv; |
| #endif |
| struct buff_s rpm; |
| struct buff_s lmem; |
| } BuffInfo_t; |
| #ifdef MULTI_INSTANCE_SUPPORT |
| #define DEC_RESULT_NONE 0 |
| #define DEC_RESULT_DONE 1 |
| #define DEC_RESULT_AGAIN 2 |
| #define DEC_RESULT_CONFIG_PARAM 3 |
| #define DEC_RESULT_ERROR 4 |
| #define DEC_INIT_PICLIST 5 |
| #define DEC_UNINIT_PICLIST 6 |
| #define DEC_RESULT_GET_DATA 7 |
| #define DEC_RESULT_GET_DATA_RETRY 8 |
| #define DEC_RESULT_EOS 9 |
| #define DEC_RESULT_FORCE_EXIT 10 |
| #define DEC_RESULT_NEED_MORE_BUFFER 11 |
| #define DEC_V4L2_CONTINUE_DECODING 18 |
| |
| #define DEC_S1_RESULT_NONE 0 |
| #define DEC_S1_RESULT_DONE 1 |
| #define DEC_S1_RESULT_FORCE_EXIT 2 |
| #define DEC_S1_RESULT_TEST_TRIGGER_DONE 0xf0 |
| |
| #ifdef FB_DECODING_TEST_SCHEDULE |
| #define TEST_SET_NONE 0 |
| #define TEST_SET_PIC_DONE 1 |
| #define TEST_SET_S2_DONE 2 |
| #endif |
| |
| static void vp9_work(struct work_struct *work); |
| #endif |
| struct loop_filter_info_n; |
| struct loopfilter; |
| struct segmentation; |
| |
| #ifdef SUPPORT_FB_DECODING |
| static void mpred_process(struct VP9Decoder_s *pbi); |
| static void vp9_s1_work(struct work_struct *work); |
| |
| struct stage_buf_s { |
| int index; |
| unsigned short rpm[RPM_END - RPM_BEGIN]; |
| }; |
| |
| static unsigned int not_run2_ready[MAX_DECODE_INSTANCE_NUM]; |
| |
| static unsigned int run2_count[MAX_DECODE_INSTANCE_NUM]; |
| |
| #ifdef FB_DECODING_TEST_SCHEDULE |
| u32 stage_buf_num; /* = 16;*/ |
| #else |
| u32 stage_buf_num; |
| #endif |
| #endif |
| |
| struct VP9Decoder_s { |
| #ifdef MULTI_INSTANCE_SUPPORT |
| unsigned char index; |
| |
| struct device *cma_dev; |
| struct platform_device *platform_dev; |
| void (*vdec_cb)(struct vdec_s *, void *); |
| void *vdec_cb_arg; |
| struct vframe_chunk_s *chunk; |
| int dec_result; |
| struct work_struct work; |
| struct work_struct recycle_mmu_work; |
| struct work_struct set_clk_work; |
| u32 start_shift_bytes; |
| |
| struct BuffInfo_s work_space_buf_store; |
| unsigned long buf_start; |
| u32 buf_size; |
| u32 cma_alloc_count; |
| unsigned long cma_alloc_addr; |
| uint8_t eos; |
| unsigned long int start_process_time; |
| unsigned last_lcu_idx; |
| int decode_timeout_count; |
| unsigned timeout_num; |
| int save_buffer_mode; |
| |
| int double_write_mode; |
| #endif |
| long used_4k_num; |
| |
| unsigned char m_ins_flag; |
| char *provider_name; |
| union param_u param; |
| int frame_count; |
| int pic_count; |
| u32 stat; |
| struct timer_list timer; |
| u32 frame_dur; |
| u32 frame_ar; |
| int fatal_error; |
| uint8_t init_flag; |
| uint8_t first_sc_checked; |
| uint8_t process_busy; |
| #define PROC_STATE_INIT 0 |
| #define PROC_STATE_DECODESLICE 1 |
| #define PROC_STATE_SENDAGAIN 2 |
| uint8_t process_state; |
| u32 ucode_pause_pos; |
| |
| int show_frame_num; |
| struct buff_s mc_buf_spec; |
| struct dec_sysinfo vvp9_amstream_dec_info; |
| void *rpm_addr; |
| void *lmem_addr; |
| dma_addr_t rpm_phy_addr; |
| dma_addr_t lmem_phy_addr; |
| unsigned short *lmem_ptr; |
| unsigned short *debug_ptr; |
| |
| void *prob_buffer_addr; |
| void *count_buffer_addr; |
| dma_addr_t prob_buffer_phy_addr; |
| dma_addr_t count_buffer_phy_addr; |
| |
| void *frame_mmu_map_addr; |
| dma_addr_t frame_mmu_map_phy_addr; |
| |
| unsigned int use_cma_flag; |
| |
| struct BUF_s m_BUF[MAX_BUF_NUM]; |
| struct MVBUF_s m_mv_BUF[MV_BUFFER_NUM]; |
| u32 used_buf_num; |
| DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE); |
| DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE); |
| DECLARE_KFIFO(pending_q, struct vframe_s *, VF_POOL_SIZE); |
| struct vframe_s vfpool[VF_POOL_SIZE]; |
| u32 vf_pre_count; |
| u32 vf_get_count; |
| u32 vf_put_count; |
| int buf_num; |
| int pic_num; |
| int lcu_size_log2; |
| unsigned int losless_comp_body_size; |
| |
| u32 video_signal_type; |
| |
| int pts_mode; |
| int last_lookup_pts; |
| int last_pts; |
| u64 last_lookup_pts_us64; |
| u64 last_pts_us64; |
| u64 shift_byte_count; |
| |
| u32 pts_unstable; |
| u32 frame_cnt_window; |
| u32 pts1, pts2; |
| u32 last_duration; |
| u32 duration_from_pts_done; |
| bool vp9_first_pts_ready; |
| |
| u32 shift_byte_count_lo; |
| u32 shift_byte_count_hi; |
| int pts_mode_switching_count; |
| int pts_mode_recovery_count; |
| |
| bool get_frame_dur; |
| u32 saved_resolution; |
| |
| /**/ |
| struct VP9_Common_s common; |
| struct RefCntBuffer_s *cur_buf; |
| int refresh_frame_flags; |
| uint8_t need_resync; |
| uint8_t hold_ref_buf; |
| uint8_t ready_for_new_data; |
| struct BufferPool_s vp9_buffer_pool; |
| |
| struct BuffInfo_s *work_space_buf; |
| |
| struct buff_s *mc_buf; |
| |
| unsigned int frame_width; |
| unsigned int frame_height; |
| |
| unsigned short *rpm_ptr; |
| int init_pic_w; |
| int init_pic_h; |
| int lcu_total; |
| int lcu_size; |
| |
| int slice_type; |
| |
| int skip_flag; |
| int decode_idx; |
| int slice_idx; |
| uint8_t has_keyframe; |
| uint8_t wait_buf; |
| uint8_t error_flag; |
| |
| /* bit 0, for decoding; bit 1, for displaying */ |
| uint8_t ignore_bufmgr_error; |
| int PB_skip_mode; |
| int PB_skip_count_after_decoding; |
| /*hw*/ |
| |
| /*lf*/ |
| int default_filt_lvl; |
| struct loop_filter_info_n *lfi; |
| struct loopfilter *lf; |
| struct segmentation *seg_4lf; |
| /**/ |
| struct vdec_info *gvs; |
| |
| u32 pre_stream_offset; |
| |
| unsigned int dec_status; |
| u32 last_put_idx; |
| int new_frame_displayed; |
| void *mmu_box; |
| void *bmmu_box; |
| int mmu_enable; |
| struct vframe_master_display_colour_s vf_dp; |
| struct firmware_s *fw; |
| int max_pic_w; |
| int max_pic_h; |
| #ifdef SUPPORT_FB_DECODING |
| int dec_s1_result; |
| int s1_test_cmd; |
| struct work_struct s1_work; |
| int used_stage_buf_num; |
| int s1_pos; |
| int s2_pos; |
| void *stage_mmu_map_addr; |
| dma_addr_t stage_mmu_map_phy_addr; |
| struct stage_buf_s *s1_buf; |
| struct stage_buf_s *s2_buf; |
| struct stage_buf_s *stage_bufs |
| [STAGE_MAX_BUFFERS]; |
| unsigned char run2_busy; |
| |
| int s1_mv_buf_index; |
| int s1_mv_buf_index_pre; |
| int s1_mv_buf_index_pre_pre; |
| unsigned long s1_mpred_mv_wr_start_addr; |
| unsigned long s1_mpred_mv_wr_start_addr_pre; |
| unsigned short s1_intra_only; |
| unsigned short s1_frame_type; |
| unsigned short s1_width; |
| unsigned short s1_height; |
| unsigned short s1_last_show_frame; |
| union param_u s1_param; |
| u8 back_not_run_ready; |
| #endif |
| int need_cache_size; |
| u64 sc_start_time; |
| bool postproc_done; |
| int low_latency_flag; |
| bool no_head; |
| bool pic_list_init_done; |
| bool pic_list_init_done2; |
| bool is_used_v4l; |
| void *v4l2_ctx; |
| bool v4l_params_parsed; |
| int frameinfo_enable; |
| struct vframe_qos_s vframe_qos; |
| u32 mem_map_mode; |
| u32 dynamic_buf_num_margin; |
| struct vframe_s vframe_dummy; |
| u32 res_ch_flag; |
| /*struct VP9Decoder_s vp9_decoder;*/ |
| union param_u vp9_param; |
| int sidebind_type; |
| int sidebind_channel_id; |
| bool enable_fence; |
| int fence_usage; |
| u32 frame_mode_pts_save[FRAME_BUFFERS]; |
| u64 frame_mode_pts64_save[FRAME_BUFFERS]; |
| int run_ready_min_buf_num; |
| int one_package_frame_cnt; |
| u32 error_frame_width; |
| u32 error_frame_height; |
| char vdec_name[32]; |
| char pts_name[32]; |
| char new_q_name[32]; |
| char disp_q_name[32]; |
| }; |
| |
| static int vp9_print(struct VP9Decoder_s *pbi, |
| int flag, const char *fmt, ...) |
| { |
| #define HEVC_PRINT_BUF 256 |
| unsigned char buf[HEVC_PRINT_BUF]; |
| int len = 0; |
| |
| if (pbi == NULL || |
| (flag == 0) || |
| (debug & flag)) { |
| va_list args; |
| |
| va_start(args, fmt); |
| if (pbi) |
| len = sprintf(buf, "[%d]", pbi->index); |
| vsnprintf(buf + len, HEVC_PRINT_BUF - len, fmt, args); |
| pr_debug("%s", buf); |
| va_end(args); |
| } |
| return 0; |
| } |
| |
| static int is_oversize(int w, int h) |
| { |
| int max = (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1)? |
| MAX_SIZE_8K : MAX_SIZE_4K; |
| |
| if (w <= 0 || h <= 0) |
| return true; |
| |
| if (h != 0 && (w > max / h)) |
| return true; |
| |
| return false; |
| } |
| |
| static int v4l_alloc_and_config_pic(struct VP9Decoder_s *pbi, |
| struct PIC_BUFFER_CONFIG_s *pic); |
| |
| static void resize_context_buffers(struct VP9Decoder_s *pbi, |
| struct VP9_Common_s *cm, int width, int height) |
| { |
| if (cm->width != width || cm->height != height) { |
| /* to do ..*/ |
| if (pbi != NULL) { |
| pbi->vp9_first_pts_ready = 0; |
| pbi->duration_from_pts_done = 0; |
| } |
| pr_info("%s (%d,%d)=>(%d,%d)\r\n", __func__, cm->width, |
| cm->height, width, height); |
| cm->width = width; |
| cm->height = height; |
| } |
| /* |
| *if (cm->cur_frame->mvs == NULL || |
| * cm->mi_rows > cm->cur_frame->mi_rows || |
| * cm->mi_cols > cm->cur_frame->mi_cols) { |
| * resize_mv_buffer(cm); |
| *} |
| */ |
| } |
| |
| static int valid_ref_frame_size(int ref_width, int ref_height, |
| int this_width, int this_height) { |
| return 2 * this_width >= ref_width && |
| 2 * this_height >= ref_height && |
| this_width <= 16 * ref_width && |
| this_height <= 16 * ref_height; |
| } |
| |
| /* |
| *static int valid_ref_frame_img_fmt(enum vpx_bit_depth_t ref_bit_depth, |
| * int ref_xss, int ref_yss, |
| * enum vpx_bit_depth_t this_bit_depth, |
| * int this_xss, int this_yss) { |
| * return ref_bit_depth == this_bit_depth && ref_xss == this_xss && |
| * ref_yss == this_yss; |
| *} |
| */ |
| |
| |
| static int setup_frame_size( |
| struct VP9Decoder_s *pbi, |
| struct VP9_Common_s *cm, union param_u *params, |
| unsigned int *mmu_index_adr, |
| int print_header_info) { |
| int width, height; |
| struct BufferPool_s * const pool = cm->buffer_pool; |
| struct PIC_BUFFER_CONFIG_s *ybf; |
| int ret = 0; |
| |
| width = params->p.width; |
| height = params->p.height; |
| if (is_oversize(width, height)) { |
| pbi->error_frame_width = width; |
| pbi->error_frame_height = height; |
| vp9_print(pbi, 0, "%s, Error: Invalid frame size\n", __func__); |
| return -1; |
| } |
| pbi->error_frame_width = 0; |
| pbi->error_frame_height = 0; |
| |
| /*vp9_read_frame_size(rb, &width, &height);*/ |
| if (print_header_info) |
| pr_info(" * 16-bits w read : %d (width : %d)\n", width, height); |
| if (print_header_info) |
| pr_info |
| (" * 16-bits h read : %d (height : %d)\n", width, height); |
| |
| WRITE_VREG(HEVC_PARSER_PICTURE_SIZE, (height << 16) | width); |
| #ifdef VP9_10B_HED_FB |
| WRITE_VREG(HEVC_ASSIST_PIC_SIZE_FB_READ, (height << 16) | width); |
| #endif |
| if (pbi->mmu_enable && ((pbi->double_write_mode & 0x10) == 0)) { |
| ret = vp9_alloc_mmu(pbi, |
| cm->new_fb_idx, |
| params->p.width, |
| params->p.height, |
| params->p.bit_depth, |
| mmu_index_adr); |
| if (ret != 0) { |
| pr_err("can't alloc need mmu1,idx %d ret =%d\n", |
| cm->new_fb_idx, |
| ret); |
| return ret; |
| } |
| cm->cur_fb_idx_mmu = cm->new_fb_idx; |
| } |
| |
| resize_context_buffers(pbi, cm, width, height); |
| setup_display_size(cm, params, print_header_info); |
| #if 0 |
| lock_buffer_pool(pool); |
| if (vp9_realloc_frame_buffer( |
| get_frame_new_buffer(cm), cm->width, cm->height, |
| cm->subsampling_x, cm->subsampling_y, |
| #if CONFIG_VP9_HIGHBITDEPTH |
| cm->use_highbitdepth, |
| #endif |
| VP9_DEC_BORDER_IN_PIXELS, |
| cm->byte_alignment, |
| &pool->frame_bufs[cm->new_fb_idx].raw_frame_buffer, |
| pool->get_fb_cb, pool->cb_priv)) { |
| unlock_buffer_pool(pool); |
| vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR, |
| "Failed to allocate frame buffer"); |
| } |
| unlock_buffer_pool(pool); |
| #else |
| /* porting */ |
| ybf = get_frame_new_buffer(cm); |
| if (!ybf) |
| return -1; |
| |
| ybf->y_crop_width = width; |
| ybf->y_crop_height = height; |
| ybf->bit_depth = params->p.bit_depth; |
| #endif |
| pool->frame_bufs[cm->new_fb_idx].buf.subsampling_x = cm->subsampling_x; |
| pool->frame_bufs[cm->new_fb_idx].buf.subsampling_y = cm->subsampling_y; |
| pool->frame_bufs[cm->new_fb_idx].buf.bit_depth = |
| (unsigned int)cm->bit_depth; |
| pool->frame_bufs[cm->new_fb_idx].buf.color_space = cm->color_space; |
| return ret; |
| } |
| |
| static int setup_frame_size_with_refs( |
| struct VP9Decoder_s *pbi, |
| struct VP9_Common_s *cm, |
| union param_u *params, |
| unsigned int *mmu_index_adr, |
| int print_header_info) { |
| |
| int width, height; |
| int found = 0, i; |
| int has_valid_ref_frame = 0; |
| struct PIC_BUFFER_CONFIG_s *ybf; |
| struct BufferPool_s * const pool = cm->buffer_pool; |
| int ret = 0; |
| |
| for (i = 0; i < REFS_PER_FRAME; ++i) { |
| if ((params->p.same_frame_size >> |
| (REFS_PER_FRAME - i - 1)) & 0x1) { |
| struct PIC_BUFFER_CONFIG_s *const buf = |
| cm->frame_refs[i].buf; |
| /*if (print_header_info) |
| * pr_info |
| * ("1-bit same_frame_size[%d] read : 1\n", i); |
| */ |
| width = buf->y_crop_width; |
| height = buf->y_crop_height; |
| /*if (print_header_info) |
| * pr_info |
| * (" - same_frame_size width : %d\n", width); |
| */ |
| /*if (print_header_info) |
| * pr_info |
| * (" - same_frame_size height : %d\n", height); |
| */ |
| found = 1; |
| break; |
| } else { |
| /*if (print_header_info) |
| * pr_info |
| * ("1-bit same_frame_size[%d] read : 0\n", i); |
| */ |
| } |
| } |
| |
| if (!found) { |
| /*vp9_read_frame_size(rb, &width, &height);*/ |
| width = params->p.width; |
| height = params->p.height; |
| /*if (print_header_info) |
| * pr_info |
| * (" * 16-bits w read : %d (width : %d)\n", |
| * width, height); |
| *if (print_header_info) |
| * pr_info |
| * (" * 16-bits h read : %d (height : %d)\n", |
| * width, height); |
| */ |
| } |
| |
| if (is_oversize(width, height)) { |
| pbi->error_frame_width = width; |
| pbi->error_frame_height = height; |
| vp9_print(pbi, 0, "%s, Error: Invalid frame size\n", __func__); |
| return -1; |
| } |
| pbi->error_frame_width = 0; |
| pbi->error_frame_height = 0; |
| |
| params->p.width = width; |
| params->p.height = height; |
| |
| WRITE_VREG(HEVC_PARSER_PICTURE_SIZE, (height << 16) | width); |
| if (pbi->mmu_enable && ((pbi->double_write_mode & 0x10) == 0)) { |
| /*if(cm->prev_fb_idx >= 0) release_unused_4k(cm->prev_fb_idx); |
| *cm->prev_fb_idx = cm->new_fb_idx; |
| */ |
| /* pr_info |
| * ("[DEBUG DEBUG]Before alloc_mmu, |
| * prev_fb_idx : %d, new_fb_idx : %d\r\n", |
| * cm->prev_fb_idx, cm->new_fb_idx); |
| */ |
| ret = vp9_alloc_mmu(pbi, cm->new_fb_idx, |
| params->p.width, params->p.height, |
| params->p.bit_depth, mmu_index_adr); |
| if (ret != 0) { |
| pr_err("can't alloc need mmu,idx %d\r\n", |
| cm->new_fb_idx); |
| return ret; |
| } |
| cm->cur_fb_idx_mmu = cm->new_fb_idx; |
| } |
| |
| /*Check to make sure at least one of frames that this frame references |
| *has valid dimensions. |
| */ |
| for (i = 0; i < REFS_PER_FRAME; ++i) { |
| struct RefBuffer_s * const ref_frame = &cm->frame_refs[i]; |
| |
| has_valid_ref_frame |= |
| valid_ref_frame_size(ref_frame->buf->y_crop_width, |
| ref_frame->buf->y_crop_height, |
| width, height); |
| } |
| if (!has_valid_ref_frame) { |
| pr_err("Error: Referenced frame has invalid size\r\n"); |
| return -1; |
| } |
| #if 0 |
| for (i = 0; i < REFS_PER_FRAME; ++i) { |
| struct RefBuffer_s * const ref_frame = |
| &cm->frame_refs[i]; |
| if (!valid_ref_frame_img_fmt( |
| ref_frame->buf->bit_depth, |
| ref_frame->buf->subsampling_x, |
| ref_frame->buf->subsampling_y, |
| cm->bit_depth, |
| cm->subsampling_x, |
| cm->subsampling_y)) |
| pr_err |
| ("Referenced frame incompatible color fmt\r\n"); |
| return -1; |
| } |
| #endif |
| resize_context_buffers(pbi, cm, width, height); |
| setup_display_size(cm, params, print_header_info); |
| |
| #if 0 |
| lock_buffer_pool(pool); |
| if (vp9_realloc_frame_buffer( |
| get_frame_new_buffer(cm), cm->width, cm->height, |
| cm->subsampling_x, cm->subsampling_y, |
| #if CONFIG_VP9_HIGHBITDEPTH |
| cm->use_highbitdepth, |
| #endif |
| VP9_DEC_BORDER_IN_PIXELS, |
| cm->byte_alignment, |
| &pool->frame_bufs[cm->new_fb_idx].raw_frame_buffer, |
| pool->get_fb_cb, |
| pool->cb_priv)) { |
| unlock_buffer_pool(pool); |
| vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR, |
| "Failed to allocate frame buffer"); |
| } |
| unlock_buffer_pool(pool); |
| #else |
| /* porting */ |
| ybf = get_frame_new_buffer(cm); |
| if (!ybf) |
| return -1; |
| |
| ybf->y_crop_width = width; |
| ybf->y_crop_height = height; |
| ybf->bit_depth = params->p.bit_depth; |
| #endif |
| pool->frame_bufs[cm->new_fb_idx].buf.subsampling_x = cm->subsampling_x; |
| pool->frame_bufs[cm->new_fb_idx].buf.subsampling_y = cm->subsampling_y; |
| pool->frame_bufs[cm->new_fb_idx].buf.bit_depth = |
| (unsigned int)cm->bit_depth; |
| pool->frame_bufs[cm->new_fb_idx].buf.color_space = cm->color_space; |
| return ret; |
| } |
| |
| static inline bool close_to(int a, int b, int m) |
| { |
| return (abs(a - b) < m) ? true : false; |
| } |
| |
| #ifdef MULTI_INSTANCE_SUPPORT |
| static int vp9_print_cont(struct VP9Decoder_s *pbi, |
| int flag, const char *fmt, ...) |
| { |
| unsigned char buf[HEVC_PRINT_BUF]; |
| int len = 0; |
| |
| if (pbi == NULL || |
| (flag == 0) || |
| (debug & flag)) { |
| va_list args; |
| |
| va_start(args, fmt); |
| vsnprintf(buf + len, HEVC_PRINT_BUF - len, fmt, args); |
| pr_debug("%s", buf); |
| va_end(args); |
| } |
| return 0; |
| } |
| |
| static void trigger_schedule(struct VP9Decoder_s *pbi) |
| { |
| if (pbi->is_used_v4l) { |
| struct aml_vcodec_ctx *ctx = |
| (struct aml_vcodec_ctx *)(pbi->v4l2_ctx); |
| |
| if (ctx->param_sets_from_ucode && |
| !pbi->v4l_params_parsed) |
| vdec_v4l_write_frame_sync(ctx); |
| } |
| |
| if (pbi->vdec_cb) |
| pbi->vdec_cb(hw_to_vdec(pbi), pbi->vdec_cb_arg); |
| } |
| |
| static void reset_process_time(struct VP9Decoder_s *pbi) |
| { |
| if (pbi->start_process_time) { |
| unsigned process_time = |
| 1000 * (jiffies - pbi->start_process_time) / HZ; |
| pbi->start_process_time = 0; |
| if (process_time > max_process_time[pbi->index]) |
| max_process_time[pbi->index] = process_time; |
| } |
| } |
| |
| static void start_process_time(struct VP9Decoder_s *pbi) |
| { |
| pbi->start_process_time = jiffies; |
| pbi->decode_timeout_count = 0; |
| pbi->last_lcu_idx = 0; |
| } |
| |
| static void timeout_process(struct VP9Decoder_s *pbi) |
| { |
| pbi->timeout_num++; |
| amhevc_stop(); |
| vp9_print(pbi, |
| 0, "%s decoder timeout\n", __func__); |
| |
| pbi->dec_result = DEC_RESULT_DONE; |
| reset_process_time(pbi); |
| vdec_schedule_work(&pbi->work); |
| } |
| |
| static u32 get_valid_double_write_mode(struct VP9Decoder_s *pbi) |
| { |
| return ((double_write_mode & 0x80000000) == 0) ? |
| pbi->double_write_mode : |
| (double_write_mode & 0x7fffffff); |
| } |
| |
| static int v4l_parser_get_double_write_mode(struct VP9Decoder_s *pbi) |
| { |
| u32 valid_dw_mode = get_valid_double_write_mode(pbi); |
| u32 dw; |
| int w, h; |
| |
| /* mask for supporting double write value bigger than 0x100 */ |
| if (valid_dw_mode & 0xffffff00) { |
| w = pbi->frame_width; |
| h = pbi->frame_height; |
| |
| dw = 0x1; /*1:1*/ |
| switch (valid_dw_mode) { |
| case 0x100: |
| if (w > 1920 && h > 1088) |
| dw = 0x4; /*1:2*/ |
| break; |
| case 0x200: |
| if (w > 1920 && h > 1088) |
| dw = 0x2; /*1:4*/ |
| break; |
| case 0x300: |
| if (w > 1280 && h > 720) |
| dw = 0x4; /*1:2*/ |
| break; |
| default: |
| break; |
| } |
| return dw; |
| } |
| |
| return valid_dw_mode; |
| } |
| |
| |
| static int get_double_write_mode(struct VP9Decoder_s *pbi) |
| { |
| u32 valid_dw_mode = get_valid_double_write_mode(pbi); |
| u32 dw; |
| int w, h; |
| struct VP9_Common_s *cm = &pbi->common; |
| struct PIC_BUFFER_CONFIG_s *cur_pic_config; |
| |
| /* mask for supporting double write value bigger than 0x100 */ |
| if (valid_dw_mode & 0xffffff00) { |
| if (!cm->cur_frame) |
| return 1;/*no valid frame,*/ |
| cur_pic_config = &cm->cur_frame->buf; |
| w = cur_pic_config->y_crop_width; |
| h = cur_pic_config->y_crop_height; |
| |
| dw = 0x1; /*1:1*/ |
| switch (valid_dw_mode) { |
| case 0x100: |
| if (w > 1920 && h > 1088) |
| dw = 0x4; /*1:2*/ |
| break; |
| case 0x200: |
| if (w > 1920 && h > 1088) |
| dw = 0x2; /*1:4*/ |
| break; |
| case 0x300: |
| if (w > 1280 && h > 720) |
| dw = 0x4; /*1:2*/ |
| break; |
| default: |
| break; |
| } |
| return dw; |
| } |
| |
| return valid_dw_mode; |
| } |
| |
| /* for double write buf alloc */ |
| static int get_double_write_mode_init(struct VP9Decoder_s *pbi) |
| { |
| u32 valid_dw_mode = get_valid_double_write_mode(pbi); |
| u32 dw; |
| int w = pbi->init_pic_w; |
| int h = pbi->init_pic_h; |
| |
| dw = 0x1; /*1:1*/ |
| switch (valid_dw_mode) { |
| case 0x100: |
| if (w > 1920 && h > 1088) |
| dw = 0x4; /*1:2*/ |
| break; |
| case 0x200: |
| if (w > 1920 && h > 1088) |
| dw = 0x2; /*1:4*/ |
| break; |
| case 0x300: |
| if (w > 1280 && h > 720) |
| dw = 0x4; /*1:2*/ |
| break; |
| default: |
| dw = valid_dw_mode; |
| break; |
| } |
| return dw; |
| } |
| #endif |
| |
| static int get_double_write_ratio(struct VP9Decoder_s *pbi, |
| int dw_mode) |
| { |
| int ratio = 1; |
| if ((dw_mode == 2) || |
| (dw_mode == 3)) |
| ratio = 4; |
| else if (dw_mode == 4) |
| ratio = 2; |
| return ratio; |
| } |
| |
| //#define MAX_4K_NUM 0x1200 |
| |
| int vp9_alloc_mmu( |
| struct VP9Decoder_s *pbi, |
| int cur_buf_idx, |
| int pic_width, |
| int pic_height, |
| unsigned short bit_depth, |
| unsigned int *mmu_index_adr) |
| { |
| int bit_depth_10 = (bit_depth == VPX_BITS_10); |
| int picture_size; |
| int cur_mmu_4k_number, max_frame_num; |
| if (!pbi->mmu_box) { |
| pr_err("error no mmu box!\n"); |
| return -1; |
| } |
| if (get_double_write_mode(pbi) == 0x10) |
| return 0; |
| if (bit_depth >= VPX_BITS_12) { |
| pbi->fatal_error = DECODER_FATAL_ERROR_SIZE_OVERFLOW; |
| pr_err("fatal_error, un support bit depth 12!\n\n"); |
| return -1; |
| } |
| picture_size = compute_losless_comp_body_size(pic_width, pic_height, |
| bit_depth_10); |
| cur_mmu_4k_number = ((picture_size + (1 << 12) - 1) >> 12); |
| |
| if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) |
| max_frame_num = MAX_FRAME_8K_NUM; |
| else |
| max_frame_num = MAX_FRAME_4K_NUM; |
| |
| if (cur_mmu_4k_number > max_frame_num) { |
| pr_err("over max !! cur_mmu_4k_number 0x%x width %d height %d\n", |
| cur_mmu_4k_number, pic_width, pic_height); |
| return -1; |
| } |
| |
| return decoder_mmu_box_alloc_idx( |
| pbi->mmu_box, |
| cur_buf_idx, |
| cur_mmu_4k_number, |
| mmu_index_adr); |
| } |
| |
| |
| #ifndef MV_USE_FIXED_BUF |
| static void dealloc_mv_bufs(struct VP9Decoder_s *pbi) |
| { |
| int i; |
| for (i = 0; i < MV_BUFFER_NUM; i++) { |
| if (pbi->m_mv_BUF[i].start_adr) { |
| if (debug) |
| pr_info( |
| "dealloc mv buf(%d) adr %ld size 0x%x used_flag %d\n", |
| i, pbi->m_mv_BUF[i].start_adr, |
| pbi->m_mv_BUF[i].size, |
| pbi->m_mv_BUF[i].used_flag); |
| decoder_bmmu_box_free_idx( |
| pbi->bmmu_box, |
| MV_BUFFER_IDX(i)); |
| pbi->m_mv_BUF[i].start_adr = 0; |
| pbi->m_mv_BUF[i].size = 0; |
| pbi->m_mv_BUF[i].used_flag = 0; |
| } |
| } |
| } |
| |
| static int alloc_mv_buf(struct VP9Decoder_s *pbi, |
| int i, int size) |
| { |
| int ret = 0; |
| |
| if (pbi->m_mv_BUF[i].start_adr && |
| size > pbi->m_mv_BUF[i].size) { |
| dealloc_mv_bufs(pbi); |
| } else if (pbi->m_mv_BUF[i].start_adr) |
| return 0; |
| |
| if (decoder_bmmu_box_alloc_buf_phy |
| (pbi->bmmu_box, |
| MV_BUFFER_IDX(i), size, |
| DRIVER_NAME, |
| &pbi->m_mv_BUF[i].start_adr) < 0) { |
| pbi->m_mv_BUF[i].start_adr = 0; |
| ret = -1; |
| } else { |
| pbi->m_mv_BUF[i].size = size; |
| pbi->m_mv_BUF[i].used_flag = 0; |
| ret = 0; |
| if (debug) { |
| pr_info( |
| "MV Buffer %d: start_adr %p size %x\n", |
| i, |
| (void *)pbi->m_mv_BUF[i].start_adr, |
| pbi->m_mv_BUF[i].size); |
| } |
| } |
| return ret; |
| } |
| |
| static int cal_mv_buf_size(struct VP9Decoder_s *pbi, int pic_width, int pic_height) |
| { |
| int lcu_size = 64; /*fixed 64*/ |
| int pic_width_64 = (pic_width + 63) & (~0x3f); |
| int pic_height_32 = (pic_height + 31) & (~0x1f); |
| int pic_width_lcu = (pic_width_64 % lcu_size) ? |
| pic_width_64 / lcu_size + 1 |
| : pic_width_64 / lcu_size; |
| int pic_height_lcu = (pic_height_32 % lcu_size) ? |
| pic_height_32 / lcu_size + 1 |
| : pic_height_32 / lcu_size; |
| int lcu_total = pic_width_lcu * pic_height_lcu; |
| int size_a = lcu_total * 36 * 16; |
| int size_b = pic_width_lcu * 16 * |
| ((pic_height_lcu >> 3) + (pic_height_lcu & 0x7)); |
| int size = (size_a + size_b + 0xffff) & |
| (~0xffff); |
| |
| return size; |
| } |
| |
| |
| static int init_mv_buf_list(struct VP9Decoder_s *pbi) |
| { |
| int i; |
| int ret = 0; |
| int count = MV_BUFFER_NUM; |
| int pic_width = pbi->init_pic_w; |
| int pic_height = pbi->init_pic_h; |
| int size = cal_mv_buf_size(pbi, pic_width, pic_height); |
| |
| if (mv_buf_dynamic_alloc) |
| return 0; |
| |
| if (mv_buf_margin > 0) |
| count = REF_FRAMES + mv_buf_margin; |
| |
| if (pbi->init_pic_w > 2048 && pbi->init_pic_h > 1088) |
| count = REF_FRAMES_4K + mv_buf_margin; |
| |
| if (debug) { |
| pr_info("%s w:%d, h:%d, count: %d\n", |
| __func__, pbi->init_pic_w, pbi->init_pic_h, count); |
| } |
| |
| for (i = 0; |
| i < count && i < MV_BUFFER_NUM; i++) { |
| if (alloc_mv_buf(pbi, i, size) < 0) { |
| ret = -1; |
| break; |
| } |
| } |
| return ret; |
| } |
| |
| static int get_mv_buf(struct VP9Decoder_s *pbi, |
| struct PIC_BUFFER_CONFIG_s *pic_config) |
| { |
| int i; |
| int ret = -1; |
| if (mv_buf_dynamic_alloc) { |
| union param_u *params = &pbi->vp9_param; |
| int size = cal_mv_buf_size(pbi, |
| params->p.width, params->p.height); |
| for (i = 0; i < MV_BUFFER_NUM; i++) { |
| if (pbi->m_mv_BUF[i].start_adr == 0) { |
| ret = i; |
| break; |
| } |
| } |
| if (i == MV_BUFFER_NUM) { |
| pr_info( |
| "%s: Error, mv buf MV_BUFFER_NUM is not enough\n", |
| __func__); |
| return ret; |
| } |
| |
| if (alloc_mv_buf(pbi, ret, size) >= 0) { |
| pic_config->mv_buf_index = ret; |
| pic_config->mpred_mv_wr_start_addr = |
| (pbi->m_mv_BUF[ret].start_adr + 0xffff) & |
| (~0xffff); |
| pic_config->mv_size = size; |
| |
| if (debug & VP9_DEBUG_BUFMGR_MORE) |
| pr_info( |
| "%s alloc => %d (%ld) size 0x%x\n", |
| __func__, ret, |
| pic_config->mpred_mv_wr_start_addr, |
| pic_config->mv_size); |
| } else { |
| pr_info( |
| "%s: Error, mv buf alloc fail\n", |
| __func__); |
| } |
| return ret; |
| } |
| |
| for (i = 0; i < MV_BUFFER_NUM; i++) { |
| if (pbi->m_mv_BUF[i].start_adr && |
| pbi->m_mv_BUF[i].used_flag == 0) { |
| pbi->m_mv_BUF[i].used_flag = 1; |
| ret = i; |
| break; |
| } |
| } |
| |
| if (ret >= 0) { |
| pic_config->mv_buf_index = ret; |
| pic_config->mpred_mv_wr_start_addr = |
| (pbi->m_mv_BUF[ret].start_adr + 0xffff) & |
| (~0xffff); |
| pic_config->mv_size = pbi->m_mv_BUF[ret].size; |
| if (debug & VP9_DEBUG_BUFMGR_MORE) |
| pr_info( |
| "%s => %d (%ld) size 0x%x\n", |
| __func__, ret, |
| pic_config->mpred_mv_wr_start_addr, |
| pic_config->mv_size); |
| } else { |
| pr_info( |
| "%s: Error, mv buf is not enough\n", |
| __func__); |
| } |
| return ret; |
| } |
| |
| static void put_mv_buf(struct VP9Decoder_s *pbi, |
| int *mv_buf_index) |
| { |
| int i = *mv_buf_index; |
| if (i >= MV_BUFFER_NUM) { |
| if (debug & VP9_DEBUG_BUFMGR_MORE) |
| pr_info( |
| "%s: index %d beyond range\n", |
| __func__, i); |
| return; |
| } |
| |
| if (mv_buf_dynamic_alloc) { |
| if (pbi->m_mv_BUF[i].start_adr) { |
| if (debug) |
| pr_info( |
| "dealloc mv buf(%d) adr %ld size 0x%x used_flag %d\n", |
| i, pbi->m_mv_BUF[i].start_adr, |
| pbi->m_mv_BUF[i].size, |
| pbi->m_mv_BUF[i].used_flag); |
| decoder_bmmu_box_free_idx( |
| pbi->bmmu_box, |
| MV_BUFFER_IDX(i)); |
| pbi->m_mv_BUF[i].start_adr = 0; |
| pbi->m_mv_BUF[i].size = 0; |
| pbi->m_mv_BUF[i].used_flag = 0; |
| } |
| *mv_buf_index = -1; |
| return; |
| } |
| if (debug & VP9_DEBUG_BUFMGR_MORE) |
| pr_info( |
| "%s(%d): used_flag(%d)\n", |
| __func__, i, |
| pbi->m_mv_BUF[i].used_flag); |
| |
| *mv_buf_index = -1; |
| if (pbi->m_mv_BUF[i].start_adr && |
| pbi->m_mv_BUF[i].used_flag) |
| pbi->m_mv_BUF[i].used_flag = 0; |
| } |
| |
| static void put_un_used_mv_bufs(struct VP9Decoder_s *pbi) |
| { |
| struct VP9_Common_s *const cm = &pbi->common; |
| struct RefCntBuffer_s *const frame_bufs = cm->buffer_pool->frame_bufs; |
| int i; |
| for (i = 0; i < pbi->used_buf_num; ++i) { |
| if ((frame_bufs[i].ref_count == 0) && |
| (frame_bufs[i].buf.index != -1) && |
| (frame_bufs[i].buf.mv_buf_index >= 0) |
| ) |
| put_mv_buf(pbi, &frame_bufs[i].buf.mv_buf_index); |
| } |
| } |
| |
| #ifdef SUPPORT_FB_DECODING |
| static bool mv_buf_available(struct VP9Decoder_s *pbi) |
| { |
| int i; |
| bool ret = 0; |
| for (i = 0; i < MV_BUFFER_NUM; i++) { |
| if (pbi->m_mv_BUF[i].start_adr && |
| pbi->m_mv_BUF[i].used_flag == 0) { |
| ret = 1; |
| break; |
| } |
| } |
| return ret; |
| } |
| #endif |
| #endif |
| |
| #ifdef SUPPORT_FB_DECODING |
| static void init_stage_buf(struct VP9Decoder_s *pbi) |
| { |
| uint i; |
| for (i = 0; i < STAGE_MAX_BUFFERS |
| && i < stage_buf_num; i++) { |
| pbi->stage_bufs[i] = |
| vmalloc(sizeof(struct stage_buf_s)); |
| if (pbi->stage_bufs[i] == NULL) { |
| vp9_print(pbi, |
| 0, "%s vmalloc fail\n", __func__); |
| break; |
| } |
| pbi->stage_bufs[i]->index = i; |
| } |
| pbi->used_stage_buf_num = i; |
| pbi->s1_pos = 0; |
| pbi->s2_pos = 0; |
| pbi->s1_buf = NULL; |
| pbi->s2_buf = NULL; |
| pbi->s1_mv_buf_index = FRAME_BUFFERS; |
| pbi->s1_mv_buf_index_pre = FRAME_BUFFERS; |
| pbi->s1_mv_buf_index_pre_pre = FRAME_BUFFERS; |
| |
| if (pbi->used_stage_buf_num > 0) |
| vp9_print(pbi, |
| 0, "%s 2 stage decoding buf %d\n", |
| __func__, |
| pbi->used_stage_buf_num); |
| } |
| |
| static void uninit_stage_buf(struct VP9Decoder_s *pbi) |
| { |
| int i; |
| for (i = 0; i < pbi->used_stage_buf_num; i++) { |
| if (pbi->stage_bufs[i]) |
| vfree(pbi->stage_bufs[i]); |
| pbi->stage_bufs[i] = NULL; |
| } |
| pbi->used_stage_buf_num = 0; |
| pbi->s1_pos = 0; |
| pbi->s2_pos = 0; |
| pbi->s1_buf = NULL; |
| pbi->s2_buf = NULL; |
| } |
| |
| static int get_s1_buf( |
| struct VP9Decoder_s *pbi) |
| { |
| struct stage_buf_s *buf = NULL; |
| int ret = -1; |
| int buf_page_num = MAX_STAGE_PAGE_NUM; |
| int next_s1_pos = pbi->s1_pos + 1; |
| |
| if (next_s1_pos >= pbi->used_stage_buf_num) |
| next_s1_pos = 0; |
| if (next_s1_pos == pbi->s2_pos) { |
| pbi->s1_buf = NULL; |
| return ret; |
| } |
| |
| buf = pbi->stage_bufs[pbi->s1_pos]; |
| ret = decoder_mmu_box_alloc_idx( |
| pbi->mmu_box, |
| buf->index, |
| buf_page_num, |
| pbi->stage_mmu_map_addr); |
| if (ret < 0) { |
| vp9_print(pbi, 0, |
| "%s decoder_mmu_box_alloc fail for index %d (s1_pos %d s2_pos %d)\n", |
| __func__, buf->index, |
| pbi->s1_pos, pbi->s2_pos); |
| buf = NULL; |
| } else { |
| vp9_print(pbi, VP9_DEBUG_2_STAGE, |
| "%s decoder_mmu_box_alloc %d page for index %d (s1_pos %d s2_pos %d)\n", |
| __func__, buf_page_num, buf->index, |
| pbi->s1_pos, pbi->s2_pos); |
| } |
| pbi->s1_buf = buf; |
| return ret; |
| } |
| |
| static void inc_s1_pos(struct VP9Decoder_s *pbi) |
| { |
| struct stage_buf_s *buf = |
| pbi->stage_bufs[pbi->s1_pos]; |
| |
| int used_page_num = |
| #ifdef FB_DECODING_TEST_SCHEDULE |
| MAX_STAGE_PAGE_NUM/2; |
| #else |
| (READ_VREG(HEVC_ASSIST_HED_FB_W_CTL) >> 16); |
| #endif |
| decoder_mmu_box_free_idx_tail(pbi->mmu_box, |
| FRAME_BUFFERS + buf->index, used_page_num); |
| |
| pbi->s1_pos++; |
| if (pbi->s1_pos >= pbi->used_stage_buf_num) |
| pbi->s1_pos = 0; |
| |
| vp9_print(pbi, VP9_DEBUG_2_STAGE, |
| "%s (used_page_num %d) for index %d (s1_pos %d s2_pos %d)\n", |
| __func__, used_page_num, buf->index, |
| pbi->s1_pos, pbi->s2_pos); |
| } |
| |
| #define s2_buf_available(pbi) (pbi->s1_pos != pbi->s2_pos) |
| |
| static int get_s2_buf( |
| struct VP9Decoder_s *pbi) |
| { |
| int ret = -1; |
| struct stage_buf_s *buf = NULL; |
| if (s2_buf_available(pbi)) { |
| buf = pbi->stage_bufs[pbi->s2_pos]; |
| vp9_print(pbi, VP9_DEBUG_2_STAGE, |
| "%s for index %d (s1_pos %d s2_pos %d)\n", |
| __func__, buf->index, |
| pbi->s1_pos, pbi->s2_pos); |
| pbi->s2_buf = buf; |
| ret = 0; |
| } |
| return ret; |
| } |
| |
| static void inc_s2_pos(struct VP9Decoder_s *pbi) |
| { |
| struct stage_buf_s *buf = |
| pbi->stage_bufs[pbi->s2_pos]; |
| decoder_mmu_box_free_idx(pbi->mmu_box, |
| FRAME_BUFFERS + buf->index); |
| pbi->s2_pos++; |
| if (pbi->s2_pos >= pbi->used_stage_buf_num) |
| pbi->s2_pos = 0; |
| vp9_print(pbi, VP9_DEBUG_2_STAGE, |
| "%s for index %d (s1_pos %d s2_pos %d)\n", |
| __func__, buf->index, |
| pbi->s1_pos, pbi->s2_pos); |
| } |
| |
| static int get_free_stage_buf_num(struct VP9Decoder_s *pbi) |
| { |
| int num; |
| if (pbi->s1_pos >= pbi->s2_pos) |
| num = pbi->used_stage_buf_num - |
| (pbi->s1_pos - pbi->s2_pos) - 1; |
| else |
| num = (pbi->s2_pos - pbi->s1_pos) - 1; |
| return num; |
| } |
| |
| #ifndef FB_DECODING_TEST_SCHEDULE |
| static DEFINE_SPINLOCK(fb_core_spin_lock); |
| |
| static u8 is_s2_decoding_finished(struct VP9Decoder_s *pbi) |
| { |
| /* to do: VLSI review |
| completion of last LCU decoding in BACK |
| */ |
| return 1; |
| } |
| |
| static void start_s1_decoding(struct VP9Decoder_s *pbi) |
| { |
| /* to do: VLSI review |
| after parser, how to start LCU decoding in BACK |
| */ |
| } |
| |
| static void fb_reset_core(struct vdec_s *vdec, u32 mask) |
| { |
| /* to do: VLSI review |
| 1. how to disconnect DMC for FRONT and BACK |
| 2. reset bit 13, 24, FRONT or BACK ?? |
| */ |
| |
| unsigned long flags; |
| u32 reset_bits = 0; |
| if (mask & HW_MASK_FRONT) |
| WRITE_VREG(HEVC_STREAM_CONTROL, 0); |
| spin_lock_irqsave(&fb_core_spin_lock, flags); |
| codec_dmcbus_write(DMC_REQ_CTRL, |
| codec_dmcbus_read(DMC_REQ_CTRL) & (~(1 << 4))); |
| spin_unlock_irqrestore(&fb_core_spin_lock, flags); |
| |
| while (!(codec_dmcbus_read(DMC_CHAN_STS) |
| & (1 << 4))) |
| ; |
| |
| if ((mask & HW_MASK_FRONT) && |
| input_frame_based(vdec)) |
| WRITE_VREG(HEVC_STREAM_CONTROL, 0); |
| |
| /* |
| * 2: assist |
| * 3: parser |
| * 4: parser_state |
| * 8: dblk |
| * 11:mcpu |
| * 12:ccpu |
| * 13:ddr |
| * 14:iqit |
| * 15:ipp |
| * 17:qdct |
| * 18:mpred |
| * 19:sao |
| * 24:hevc_afifo |
| */ |
| if (mask & HW_MASK_FRONT) { |
| reset_bits = |
| (1<<3)|(1<<4)|(1<<11)| |
| (1<<12)|(1<<18); |
| } |
| if (mask & HW_MASK_BACK) { |
| reset_bits = |
| (1<<8)|(1<<13)|(1<<14)|(1<<15)| |
| (1<<17)|(1<<19)|(1<<24); |
| } |
| WRITE_VREG(DOS_SW_RESET3, reset_bits); |
| #if 0 |
| (1<<3)|(1<<4)|(1<<8)|(1<<11)| |
| (1<<12)|(1<<13)|(1<<14)|(1<<15)| |
| (1<<17)|(1<<18)|(1<<19)|(1<<24); |
| #endif |
| WRITE_VREG(DOS_SW_RESET3, 0); |
| |
| |
| spin_lock_irqsave(&fb_core_spin_lock, flags); |
| codec_dmcbus_write(DMC_REQ_CTRL, |
| codec_dmcbus_read(DMC_REQ_CTRL) | (1 << 4)); |
| spin_unlock_irqrestore(&fb_core_spin_lock, flags); |
| |
| } |
| #endif |
| |
| #endif |
| |
| static void init_pic_list_hw(struct VP9Decoder_s *pbi); |
| |
| static int get_free_fb(struct VP9Decoder_s *pbi) |
| { |
| struct VP9_Common_s *const cm = &pbi->common; |
| struct RefCntBuffer_s *const frame_bufs = cm->buffer_pool->frame_bufs; |
| int i; |
| unsigned long flags; |
| |
| lock_buffer_pool(cm->buffer_pool, flags); |
| if (debug & VP9_DEBUG_BUFMGR_MORE) { |
| for (i = 0; i < pbi->used_buf_num; ++i) { |
| pr_info("%s:%d, ref_count %d vf_ref %d index %d\r\n", |
| __func__, i, frame_bufs[i].ref_count, |
| frame_bufs[i].buf.vf_ref, |
| frame_bufs[i].buf.index); |
| } |
| } |
| for (i = 0; i < pbi->used_buf_num; ++i) { |
| if ((frame_bufs[i].ref_count == 0) && |
| (frame_bufs[i].buf.vf_ref == 0) && |
| (frame_bufs[i].buf.index != -1) |
| ) |
| break; |
| } |
| if (i != pbi->used_buf_num) { |
| frame_bufs[i].ref_count = 1; |
| /*pr_info("[MMU DEBUG 1] set ref_count[%d] : %d\r\n", |
| i, frame_bufs[i].ref_count);*/ |
| } else { |
| /* Reset i to be INVALID_IDX to indicate |
| no free buffer found*/ |
| i = INVALID_IDX; |
| } |
| |
| unlock_buffer_pool(cm->buffer_pool, flags); |
| return i; |
| } |
| |
| static int v4l_get_free_fb(struct VP9Decoder_s *pbi) |
| { |
| struct VP9_Common_s *const cm = &pbi->common; |
| struct RefCntBuffer_s *const frame_bufs = cm->buffer_pool->frame_bufs; |
| struct aml_vcodec_ctx * v4l = pbi->v4l2_ctx; |
| struct v4l_buff_pool *pool = &v4l->cap_pool; |
| struct PIC_BUFFER_CONFIG_s *pic = NULL; |
| int i, idx = INVALID_IDX; |
| ulong flags; |
| |
| lock_buffer_pool(cm->buffer_pool, flags); |
| |
| for (i = 0; i < pool->in; ++i) { |
| u32 state = (pool->seq[i] >> 16); |
| u32 index = (pool->seq[i] & 0xffff); |
| |
| switch (state) { |
| case V4L_CAP_BUFF_IN_DEC: |
| pic = &frame_bufs[i].buf; |
| if ((frame_bufs[i].ref_count == 0) && |
| (pic->vf_ref == 0) && |
| (pic->index != -1) && |
| pic->cma_alloc_addr) { |
| idx = i; |
| } |
| break; |
| case V4L_CAP_BUFF_IN_M2M: |
| pic = &frame_bufs[index].buf; |
| pic->y_crop_width = pbi->frame_width; |
| pic->y_crop_height = pbi->frame_height; |
| if (!v4l_alloc_and_config_pic(pbi, pic)) { |
| set_canvas(pbi, pic); |
| init_pic_list_hw(pbi); |
| idx = index; |
| } |
| break; |
| default: |
| pr_err("v4l buffer state err %d.\n", state); |
| break; |
| } |
| |
| if (idx != INVALID_IDX) { |
| frame_bufs[idx].ref_count = 1; |
| break; |
| } |
| } |
| |
| unlock_buffer_pool(cm->buffer_pool, flags); |
| |
| return idx; |
| } |
| |
| static int get_free_buf_count(struct VP9Decoder_s *pbi) |
| { |
| struct VP9_Common_s *const cm = &pbi->common; |
| struct RefCntBuffer_s *const frame_bufs = cm->buffer_pool->frame_bufs; |
| int i; |
| int free_buf_count = 0; |
| for (i = 0; i < pbi->used_buf_num; ++i) |
| if ((frame_bufs[i].ref_count == 0) && |
| (frame_bufs[i].buf.vf_ref == 0) && |
| (frame_bufs[i].buf.index != -1) |
| ) |
| free_buf_count++; |
| return free_buf_count; |
| } |
| |
| static void decrease_ref_count(int idx, struct RefCntBuffer_s *const frame_bufs, |
| struct BufferPool_s *const pool) |
| { |
| if (idx >= 0) { |
| --frame_bufs[idx].ref_count; |
| /*pr_info("[MMU DEBUG 7] dec ref_count[%d] : %d\r\n", idx, |
| * frame_bufs[idx].ref_count); |
| */ |
| /*A worker may only get a free framebuffer index when |
| *calling get_free_fb. But the private buffer is not set up |
| *until finish decoding header. So any error happens during |
| *decoding header, the frame_bufs will not have valid priv |
| *buffer. |
| */ |
| |
| if (frame_bufs[idx].ref_count == 0 && |
| frame_bufs[idx].raw_frame_buffer.priv) |
| vp9_release_frame_buffer |
| (&frame_bufs[idx].raw_frame_buffer); |
| } |
| } |
| |
| static void generate_next_ref_frames(struct VP9Decoder_s *pbi) |
| { |
| struct VP9_Common_s *const cm = &pbi->common; |
| struct RefCntBuffer_s *frame_bufs = cm->buffer_pool->frame_bufs; |
| struct BufferPool_s *const pool = cm->buffer_pool; |
| int mask, ref_index = 0; |
| unsigned long flags; |
| |
| /* Generate next_ref_frame_map.*/ |
| lock_buffer_pool(pool, flags); |
| for (mask = pbi->refresh_frame_flags; mask; mask >>= 1) { |
| if (mask & 1) { |
| cm->next_ref_frame_map[ref_index] = cm->new_fb_idx; |
| ++frame_bufs[cm->new_fb_idx].ref_count; |
| /*pr_info("[MMU DEBUG 4] inc ref_count[%d] : %d\r\n", |
| *cm->new_fb_idx, frame_bufs[cm->new_fb_idx].ref_count); |
| */ |
| } else |
| cm->next_ref_frame_map[ref_index] = |
| cm->ref_frame_map[ref_index]; |
| /* Current thread holds the reference frame.*/ |
| if (cm->ref_frame_map[ref_index] >= 0) { |
| ++frame_bufs[cm->ref_frame_map[ref_index]].ref_count; |
| /*pr_info |
| *("[MMU DEBUG 5] inc ref_count[%d] : %d\r\n", |
| *cm->ref_frame_map[ref_index], |
| *frame_bufs[cm->ref_frame_map[ref_index]].ref_count); |
| */ |
| } |
| ++ref_index; |
| } |
| |
| for (; ref_index < REF_FRAMES; ++ref_index) { |
| cm->next_ref_frame_map[ref_index] = |
| cm->ref_frame_map[ref_index]; |
| /* Current thread holds the reference frame.*/ |
| if (cm->ref_frame_map[ref_index] >= 0) { |
| ++frame_bufs[cm->ref_frame_map[ref_index]].ref_count; |
| /*pr_info("[MMU DEBUG 6] inc ref_count[%d] : %d\r\n", |
| *cm->ref_frame_map[ref_index], |
| *frame_bufs[cm->ref_frame_map[ref_index]].ref_count); |
| */ |
| } |
| } |
| unlock_buffer_pool(pool, flags); |
| return; |
| } |
| |
| static void refresh_ref_frames(struct VP9Decoder_s *pbi) |
| |
| { |
| struct VP9_Common_s *const cm = &pbi->common; |
| struct BufferPool_s *pool = cm->buffer_pool; |
| struct RefCntBuffer_s *frame_bufs = cm->buffer_pool->frame_bufs; |
| int mask, ref_index = 0; |
| unsigned long flags; |
| |
| lock_buffer_pool(pool, flags); |
| for (mask = pbi->refresh_frame_flags; mask; mask >>= 1) { |
| const int old_idx = cm->ref_frame_map[ref_index]; |
| /*Current thread releases the holding of reference frame.*/ |
| decrease_ref_count(old_idx, frame_bufs, pool); |
| |
| /*Release the reference frame in reference map.*/ |
| if ((mask & 1) && old_idx >= 0) |
| decrease_ref_count(old_idx, frame_bufs, pool); |
| cm->ref_frame_map[ref_index] = |
| cm->next_ref_frame_map[ref_index]; |
| ++ref_index; |
| } |
| |
| /*Current thread releases the holding of reference frame.*/ |
| for (; ref_index < REF_FRAMES && !cm->show_existing_frame; |
| ++ref_index) { |
| const int old_idx = cm->ref_frame_map[ref_index]; |
| |
| decrease_ref_count(old_idx, frame_bufs, pool); |
| cm->ref_frame_map[ref_index] = |
| cm->next_ref_frame_map[ref_index]; |
| } |
| unlock_buffer_pool(pool, flags); |
| return; |
| } |
| |
| int vp9_bufmgr_process(struct VP9Decoder_s *pbi, union param_u *params) |
| { |
| struct VP9_Common_s *const cm = &pbi->common; |
| struct BufferPool_s *pool = cm->buffer_pool; |
| struct RefCntBuffer_s *frame_bufs = cm->buffer_pool->frame_bufs; |
| struct PIC_BUFFER_CONFIG_s *pic = NULL; |
| int i; |
| int ret; |
| |
| pbi->ready_for_new_data = 0; |
| |
| if (pbi->has_keyframe == 0 && |
| params->p.frame_type != KEY_FRAME){ |
| on_no_keyframe_skiped++; |
| return -2; |
| } |
| pbi->has_keyframe = 1; |
| on_no_keyframe_skiped = 0; |
| #if 0 |
| if (pbi->mmu_enable) { |
| if (!pbi->m_ins_flag) |
| pbi->used_4k_num = (READ_VREG(HEVC_SAO_MMU_STATUS) >> 16); |
| if (cm->prev_fb_idx >= 0) { |
| decoder_mmu_box_free_idx_tail(pbi->mmu_box, |
| cm->prev_fb_idx, pbi->used_4k_num); |
| } |
| } |
| #endif |
| if (cm->new_fb_idx >= 0 |
| && frame_bufs[cm->new_fb_idx].ref_count == 0){ |
| vp9_release_frame_buffer |
| (&frame_bufs[cm->new_fb_idx].raw_frame_buffer); |
| } |
| /*pr_info("Before get_free_fb, prev_fb_idx : %d, new_fb_idx : %d\r\n", |
| cm->prev_fb_idx, cm->new_fb_idx);*/ |
| #ifndef MV_USE_FIXED_BUF |
| put_un_used_mv_bufs(pbi); |
| if (debug & VP9_DEBUG_BUFMGR_DETAIL) |
| dump_pic_list(pbi); |
| #endif |
| cm->new_fb_idx = pbi->is_used_v4l ? |
| v4l_get_free_fb(pbi) : |
| get_free_fb(pbi); |
| if (cm->new_fb_idx == INVALID_IDX) { |
| pr_info("get_free_fb error\r\n"); |
| return -1; |
| } |
| |
| #ifndef MV_USE_FIXED_BUF |
| #ifdef SUPPORT_FB_DECODING |
| if (pbi->used_stage_buf_num == 0) { |
| #endif |
| if (get_mv_buf(pbi, |
| &pool->frame_bufs[cm->new_fb_idx]. |
| buf) < 0) { |
| pr_info("get_mv_buf fail\r\n"); |
| return -1; |
| } |
| if (debug & VP9_DEBUG_BUFMGR_DETAIL) |
| dump_pic_list(pbi); |
| #ifdef SUPPORT_FB_DECODING |
| } |
| #endif |
| #endif |
| cm->cur_frame = &pool->frame_bufs[cm->new_fb_idx]; |
| /*if (debug & VP9_DEBUG_BUFMGR) |
| pr_info("[VP9 DEBUG]%s(get_free_fb): %d\r\n", __func__, |
| cm->new_fb_idx);*/ |
| |
| pbi->cur_buf = &frame_bufs[cm->new_fb_idx]; |
| if (pbi->mmu_enable) { |
| /* moved to after picture size ready |
| *alloc_mmu(cm, params->p.width, params->p.height, |
| *params->p.bit_depth, pbi->frame_mmu_map_addr); |
| */ |
| cm->prev_fb_idx = cm->new_fb_idx; |
| } |
| /*read_uncompressed_header()*/ |
| cm->last_frame_type = cm->frame_type; |
| cm->last_intra_only = cm->intra_only; |
| cm->profile = params->p.profile; |
| if (cm->profile >= MAX_PROFILES) { |
| pr_err("Error: Unsupported profile %d\r\n", cm->profile); |
| return -1; |
| } |
| cm->show_existing_frame = params->p.show_existing_frame; |
| if (cm->show_existing_frame) { |
| /* Show an existing frame directly.*/ |
| int frame_to_show_idx = params->p.frame_to_show_idx; |
| int frame_to_show; |
| unsigned long flags; |
| if (frame_to_show_idx >= REF_FRAMES) { |
| pr_info("frame_to_show_idx %d exceed max index\r\n", |
| frame_to_show_idx); |
| return -1; |
| } |
| |
| frame_to_show = cm->ref_frame_map[frame_to_show_idx]; |
| /*pr_info("frame_to_show %d\r\n", frame_to_show);*/ |
| lock_buffer_pool(pool, flags); |
| if (frame_to_show < 0 || |
| frame_bufs[frame_to_show].ref_count < 1) { |
| unlock_buffer_pool(pool, flags); |
| pr_err |
| ("Error:Buffer %d does not contain a decoded frame", |
| frame_to_show); |
| return -1; |
| } |
| |
| ref_cnt_fb(frame_bufs, &cm->new_fb_idx, frame_to_show); |
| unlock_buffer_pool(pool, flags); |
| pbi->refresh_frame_flags = 0; |
| /*cm->lf.filter_level = 0;*/ |
| cm->show_frame = 1; |
| |
| /* |
| *if (pbi->frame_parallel_decode) { |
| * for (i = 0; i < REF_FRAMES; ++i) |
| * cm->next_ref_frame_map[i] = |
| * cm->ref_frame_map[i]; |
| *} |
| */ |
| /* do not decode, search next start code */ |
| return 1; |
| } |
| cm->frame_type = params->p.frame_type; |
| cm->show_frame = params->p.show_frame; |
| cm->bit_depth = params->p.bit_depth; |
| cm->error_resilient_mode = params->p.error_resilient_mode; |
| |
| |
| if (cm->frame_type == KEY_FRAME) { |
| pbi->refresh_frame_flags = (1 << REF_FRAMES) - 1; |
| |
| for (i = 0; i < REFS_PER_FRAME; ++i) { |
| cm->frame_refs[i].idx = INVALID_IDX; |
| cm->frame_refs[i].buf = NULL; |
| } |
| |
| ret = setup_frame_size(pbi, |
| cm, params, pbi->frame_mmu_map_addr, |
| print_header_info); |
| if (ret) |
| return -1; |
| if (pbi->need_resync) { |
| memset(&cm->ref_frame_map, -1, |
| sizeof(cm->ref_frame_map)); |
| pbi->need_resync = 0; |
| } |
| } else { |
| cm->intra_only = cm->show_frame ? 0 : params->p.intra_only; |
| /*if (print_header_info) { |
| * if (cm->show_frame) |
| * pr_info |
| * ("intra_only set to 0 because of show_frame\n"); |
| * else |
| * pr_info |
| * ("1-bit intra_only read: %d\n", cm->intra_only); |
| *} |
| */ |
| |
| |
| cm->reset_frame_context = cm->error_resilient_mode ? |
| 0 : params->p.reset_frame_context; |
| if (print_header_info) { |
| if (cm->error_resilient_mode) |
| pr_info |
| ("reset to 0 error_resilient_mode\n"); |
| else |
| pr_info |
| (" * 2-bits reset_frame_context read : %d\n", |
| cm->reset_frame_context); |
| } |
| |
| if (cm->intra_only) { |
| if (cm->profile > PROFILE_0) { |
| /*read_bitdepth_colorspace_sampling(cm, |
| * rb, print_header_info); |
| */ |
| } else { |
| /*NOTE: The intra-only frame header |
| *does not include the specification |
| *of either the color format or |
| *color sub-sampling |
| *in profile 0. VP9 specifies that the default |
| *color format should be YUV 4:2:0 in this |
| *case (normative). |
| */ |
| cm->color_space = VPX_CS_BT_601; |
| cm->subsampling_y = cm->subsampling_x = 1; |
| cm->bit_depth = VPX_BITS_8; |
| cm->use_highbitdepth = 0; |
| } |
| |
| pbi->refresh_frame_flags = |
| params->p.refresh_frame_flags; |
| /*if (print_header_info) |
| * pr_info("*%d-bits refresh_frame read:0x%x\n", |
| * REF_FRAMES, pbi->refresh_frame_flags); |
| */ |
| ret = setup_frame_size(pbi, |
| cm, |
| params, |
| pbi->frame_mmu_map_addr, |
| print_header_info); |
| if (ret) |
| return -1; |
| if (pbi->need_resync) { |
| memset(&cm->ref_frame_map, -1, |
| sizeof(cm->ref_frame_map)); |
| pbi->need_resync = 0; |
| } |
| } else if (pbi->need_resync != 1) { /* Skip if need resync */ |
| pbi->refresh_frame_flags = |
| params->p.refresh_frame_flags; |
| if (print_header_info) |
| pr_info |
| ("*%d-bits refresh_frame read:0x%x\n", |
| REF_FRAMES, pbi->refresh_frame_flags); |
| for (i = 0; i < REFS_PER_FRAME; ++i) { |
| const int ref = |
| (params->p.ref_info >> |
| (((REFS_PER_FRAME-i-1)*4)+1)) |
| & 0x7; |
| const int idx = |
| cm->ref_frame_map[ref]; |
| struct RefBuffer_s * const ref_frame = |
| &cm->frame_refs[i]; |
| if (print_header_info) |
| pr_info("*%d-bits ref[%d]read:%d\n", |
| REF_FRAMES_LOG2, i, ref); |
| ref_frame->idx = idx; |
| ref_frame->buf = &frame_bufs[idx].buf; |
| cm->ref_frame_sign_bias[LAST_FRAME + i] |
| = (params->p.ref_info >> |
| ((REFS_PER_FRAME-i-1)*4)) & 0x1; |
| if (print_header_info) |
| pr_info("1bit ref_frame_sign_bias"); |
| /*pr_info |
| *("%dread: %d\n", |
| *LAST_FRAME+i, |
| *cm->ref_frame_sign_bias |
| *[LAST_FRAME + i]); |
| */ |
| /*pr_info |
| *("[VP9 DEBUG]%s(get ref):%d\r\n", |
| *__func__, ref_frame->idx); |
| */ |
| |
| } |
| |
| ret = setup_frame_size_with_refs( |
| pbi, |
| cm, |
| params, |
| pbi->frame_mmu_map_addr, |
| print_header_info); |
| if (ret) |
| return -1; |
| for (i = 0; i < REFS_PER_FRAME; ++i) { |
| /*struct RefBuffer_s *const ref_buf = |
| *&cm->frame_refs[i]; |
| */ |
| /* to do: |
| *vp9_setup_scale_factors_for_frame |
| */ |
| } |
| } |
| } |
| |
| pic = get_frame_new_buffer(cm); |
| if (!pic) |
| return -1; |
| |
| pic->bit_depth = cm->bit_depth; |
| pic->color_space = cm->color_space; |
| pic->slice_type = cm->frame_type; |
| |
| if (pbi->need_resync) { |
| pr_err |
| ("Error: Keyframe/intra-only frame required to reset\r\n"); |
| return -1; |
| } |
| generate_next_ref_frames(pbi); |
| pbi->hold_ref_buf = 1; |
| |
| #if 0 |
| if (frame_is_intra_only(cm) || cm->error_resilient_mode) |
| vp9_setup_past_independence(cm); |
| setup_loopfilter(&cm->lf, rb, print_header_info); |
| setup_quantization(cm, &pbi->mb, rb, print_header_info); |
| setup_segmentation(&cm->seg, rb, print_header_info); |
| setup_segmentation_dequant(cm, print_header_info); |
| |
| setup_tile_info(cm, rb, print_header_info); |
| sz = vp9_rb_read_literal(rb, 16); |
| if (print_header_info) |
| pr_info(" * 16-bits size read : %d (0x%x)\n", sz, sz); |
| |
| if (sz == 0) |
| vpx_internal_error(&cm->error, VPX_CODEC_CORRUPT_FRAME, |
| "Invalid header size"); |
| #endif |
| /*end read_uncompressed_header()*/ |
| cm->use_prev_frame_mvs = !cm->error_resilient_mode && |
| cm->width == cm->last_width && |
| cm->height == cm->last_height && |
| !cm->last_intra_only && |
| cm->last_show_frame && |
| (cm->last_frame_type != KEY_FRAME); |
| |
| /*pr_info |
| *("set use_prev_frame_mvs to %d (last_width %d last_height %d", |
| *cm->use_prev_frame_mvs, cm->last_width, cm->last_height); |
| *pr_info |
| *(" last_intra_only %d last_show_frame %d last_frame_type %d)\n", |
| *cm->last_intra_only, cm->last_show_frame, cm->last_frame_type); |
| */ |
| |
| if (pbi->enable_fence && cm->show_frame) { |
| struct PIC_BUFFER_CONFIG_s *pic = &cm->cur_frame->buf; |
| struct vdec_s *vdec = hw_to_vdec(pbi); |
| |
| /* create fence for each buffers. */ |
| ret = vdec_timeline_create_fence(&vdec->sync); |
| if (ret < 0) |
| return ret; |
| |
| pic->fence = vdec->sync.fence; |
| pic->bit_depth = cm->bit_depth; |
| pic->slice_type = cm->frame_type; |
| pic->stream_offset = pbi->pre_stream_offset; |
| |
| if (pbi->chunk) { |
| pic->pts = pbi->chunk->pts; |
| pic->pts64 = pbi->chunk->pts64; |
| pic->timestamp = pbi->chunk->timestamp; |
| } |
| |
| /* post video vframe. */ |
| prepare_display_buf(pbi, pic); |
| } |
| |
| return 0; |
| } |
| |
| |
| void swap_frame_buffers(struct VP9Decoder_s *pbi) |
| { |
| int ref_index = 0; |
| struct VP9_Common_s *const cm = &pbi->common; |
| struct BufferPool_s *const pool = cm->buffer_pool; |
| struct RefCntBuffer_s *const frame_bufs = cm->buffer_pool->frame_bufs; |
| unsigned long flags; |
| refresh_ref_frames(pbi); |
| pbi->hold_ref_buf = 0; |
| cm->frame_to_show = get_frame_new_buffer(cm); |
| |
| if (cm->frame_to_show) { |
| /*if (!pbi->frame_parallel_decode || !cm->show_frame) {*/ |
| lock_buffer_pool(pool, flags); |
| --frame_bufs[cm->new_fb_idx].ref_count; |
| /*pr_info("[MMU DEBUG 8] dec ref_count[%d] : %d\r\n", cm->new_fb_idx, |
| * frame_bufs[cm->new_fb_idx].ref_count); |
| */ |
| unlock_buffer_pool(pool, flags); |
| /*}*/ |
| } |
| |
| /*Invalidate these references until the next frame starts.*/ |
| for (ref_index = 0; ref_index < 3; ref_index++) |
| cm->frame_refs[ref_index].idx = -1; |
| } |
| |
| #if 0 |
| static void check_resync(vpx_codec_alg_priv_t *const ctx, |
| const struct VP9Decoder_s *const pbi) |
| { |
| /* Clear resync flag if worker got a key frame or intra only frame.*/ |
| if (ctx->need_resync == 1 && pbi->need_resync == 0 && |
| (pbi->common.intra_only || pbi->common.frame_type == KEY_FRAME)) |
| ctx->need_resync = 0; |
| } |
| #endif |
| |
| int vp9_get_raw_frame(struct VP9Decoder_s *pbi, struct PIC_BUFFER_CONFIG_s *sd) |
| { |
| struct VP9_Common_s *const cm = &pbi->common; |
| int ret = -1; |
| |
| if (pbi->ready_for_new_data == 1) |
| return ret; |
| |
| pbi->ready_for_new_data = 1; |
| |
| /* no raw frame to show!!! */ |
| if (!cm->show_frame) |
| return ret; |
| |
| /* may not be get buff in v4l2 */ |
| if (!cm->frame_to_show) |
| return ret; |
| |
| pbi->ready_for_new_data = 1; |
| |
| *sd = *cm->frame_to_show; |
| ret = 0; |
| |
| return ret; |
| } |
| |
| int vp9_bufmgr_init(struct VP9Decoder_s *pbi, struct BuffInfo_s *buf_spec_i, |
| struct buff_s *mc_buf_i) { |
| struct VP9_Common_s *cm = &pbi->common; |
| |
| /*memset(pbi, 0, sizeof(struct VP9Decoder_s));*/ |
| pbi->frame_count = 0; |
| pbi->pic_count = 0; |
| pbi->pre_stream_offset = 0; |
| cm->buffer_pool = &pbi->vp9_buffer_pool; |
| spin_lock_init(&cm->buffer_pool->lock); |
| cm->prev_fb_idx = INVALID_IDX; |
| cm->new_fb_idx = INVALID_IDX; |
| pbi->used_4k_num = -1; |
| cm->cur_fb_idx_mmu = INVALID_IDX; |
| pr_debug |
| ("After vp9_bufmgr_init, prev_fb_idx : %d, new_fb_idx : %d\r\n", |
| cm->prev_fb_idx, cm->new_fb_idx); |
| pbi->need_resync = 1; |
| /* Initialize the references to not point to any frame buffers.*/ |
| memset(&cm->ref_frame_map, -1, sizeof(cm->ref_frame_map)); |
| memset(&cm->next_ref_frame_map, -1, sizeof(cm->next_ref_frame_map)); |
| cm->current_video_frame = 0; |
| pbi->ready_for_new_data = 1; |
| |
| /* private init */ |
| pbi->work_space_buf = buf_spec_i; |
| if (!pbi->mmu_enable) |
| pbi->mc_buf = mc_buf_i; |
| |
| pbi->rpm_addr = NULL; |
| pbi->lmem_addr = NULL; |
| |
| pbi->use_cma_flag = 0; |
| pbi->decode_idx = 0; |
| pbi->slice_idx = 0; |
| /*int m_uiMaxCUWidth = 1<<7;*/ |
| /*int m_uiMaxCUHeight = 1<<7;*/ |
| pbi->has_keyframe = 0; |
| pbi->skip_flag = 0; |
| pbi->wait_buf = 0; |
| pbi->error_flag = 0; |
| |
| pbi->pts_mode = PTS_NORMAL; |
| pbi->last_pts = 0; |
| pbi->last_lookup_pts = 0; |
| pbi->last_pts_us64 = 0; |
| pbi->last_lookup_pts_us64 = 0; |
| pbi->shift_byte_count = 0; |
| pbi->shift_byte_count_lo = 0; |
| pbi->shift_byte_count_hi = 0; |
| pbi->pts_mode_switching_count = 0; |
| pbi->pts_mode_recovery_count = 0; |
| |
| pbi->buf_num = 0; |
| pbi->pic_num = 0; |
| |
| return 0; |
| } |
| |
| int vp9_bufmgr_postproc(struct VP9Decoder_s *pbi) |
| { |
| struct vdec_s *vdec = hw_to_vdec(pbi); |
| struct VP9_Common_s *cm = &pbi->common; |
| struct PIC_BUFFER_CONFIG_s sd; |
| |
| if (pbi->postproc_done) |
| return 0; |
| pbi->postproc_done = 1; |
| swap_frame_buffers(pbi); |
| if (!cm->show_existing_frame) { |
| cm->last_show_frame = cm->show_frame; |
| cm->prev_frame = cm->cur_frame; |
| #if 0 |
| if (cm->seg.enabled && !pbi->frame_parallel_decode) |
| vp9_swap_current_and_last_seg_map(cm); |
| #endif |
| } |
| cm->last_width = cm->width; |
| cm->last_height = cm->height; |
| if (cm->show_frame) |
| cm->current_video_frame++; |
| |
| if (vp9_get_raw_frame(pbi, &sd) == 0) { |
| /*pr_info("Display frame index %d\r\n", sd.index);*/ |
| sd.stream_offset = pbi->pre_stream_offset; |
| |
| if (pbi->enable_fence) { |
| /* notify signal to wake up wq of fence. */ |
| vdec_timeline_increase(&vdec->sync, 1); |
| } else { |
| prepare_display_buf(pbi, &sd); |
| } |
| |
| pbi->pre_stream_offset = READ_VREG(HEVC_SHIFT_BYTE_COUNT); |
| } |
| |
| /* else |
| * pr_info |
| * ("Not display this frame,ready_for_new_data%d show_frame%d\r\n", |
| * pbi->ready_for_new_data, cm->show_frame); |
| */ |
| return 0; |
| } |
| |
| /************************************************** |
| * |
| *VP9 buffer management end |
| * |
| *************************************************** |
| */ |
| |
| |
| #define HEVC_CM_BODY_START_ADDR 0x3626 |
| #define HEVC_CM_BODY_LENGTH 0x3627 |
| #define HEVC_CM_HEADER_LENGTH 0x3629 |
| #define HEVC_CM_HEADER_OFFSET 0x362b |
| |
| #define LOSLESS_COMPRESS_MODE |
| |
| /*#define DECOMP_HEADR_SURGENT*/ |
| #ifdef VP9_10B_NV21 |
| static u32 mem_map_mode = 2 /* 0:linear 1:32x32 2:64x32*/ |
| #else |
| static u32 mem_map_mode; /* 0:linear 1:32x32 2:64x32 ; m8baby test1902 */ |
| #endif |
| static u32 enable_mem_saving = 1; |
| static u32 force_w_h; |
| |
| static u32 force_fps; |
| |
| |
| const u32 vp9_version = 201602101; |
| static u32 debug; |
| static u32 radr; |
| static u32 rval; |
| static u32 pop_shorts; |
| static u32 dbg_cmd; |
| static u32 dbg_skip_decode_index; |
| static u32 endian = 0xff0; |
| #ifdef ERROR_HANDLE_DEBUG |
| static u32 dbg_nal_skip_flag; |
| /* bit[0], skip vps; bit[1], skip sps; bit[2], skip pps */ |
| static u32 dbg_nal_skip_count; |
| #endif |
| /*for debug*/ |
| static u32 decode_pic_begin; |
| static uint slice_parse_begin; |
| static u32 step; |
| #ifdef MIX_STREAM_SUPPORT |
| static u32 buf_alloc_width = 4096; |
| static u32 buf_alloc_height = 2304; |
| static u32 vp9_max_pic_w = 4096; |
| static u32 vp9_max_pic_h = 2304; |
| |
| static u32 dynamic_buf_num_margin; |
| #else |
| static u32 buf_alloc_width; |
| static u32 buf_alloc_height; |
| static u32 dynamic_buf_num_margin = 7; |
| #endif |
| static u32 buf_alloc_depth = 10; |
| static u32 buf_alloc_size; |
| /* |
| *bit[0]: 0, |
| * bit[1]: 0, always release cma buffer when stop |
| * bit[1]: 1, never release cma buffer when stop |
| *bit[0]: 1, when stop, release cma buffer if blackout is 1; |
| *do not release cma buffer is blackout is not 1 |
| * |
| *bit[2]: 0, when start decoding, check current displayed buffer |
| * (only for buffer decoded by vp9) if blackout is 0 |
| * 1, do not check current displayed buffer |
| * |
| *bit[3]: 1, if blackout is not 1, do not release current |
| * displayed cma buffer always. |
| */ |
| /* set to 1 for fast play; |
| * set to 8 for other case of "keep last frame" |
| */ |
| static u32 buffer_mode = 1; |
| /* buffer_mode_dbg: debug only*/ |
| static u32 buffer_mode_dbg = 0xffff0000; |
| /**/ |
| |
| /* |
| *bit 0, 1: only display I picture; |
| *bit 1, 1: only decode I picture; |
| */ |
| static u32 i_only_flag; |
| |
| static u32 low_latency_flag; |
| |
| static u32 no_head; |
| |
| static u32 max_decoding_time; |
| /* |
| *error handling |
| */ |
| /*error_handle_policy: |
| *bit 0: 0, auto skip error_skip_nal_count nals before error recovery; |
| *1, skip error_skip_nal_count nals before error recovery; |
| *bit 1 (valid only when bit0 == 1): |
| *1, wait vps/sps/pps after error recovery; |
| *bit 2 (valid only when bit0 == 0): |
| *0, auto search after error recovery (vp9_recover() called); |
| *1, manual search after error recovery |
| *(change to auto search after get IDR: WRITE_VREG(NAL_SEARCH_CTL, 0x2)) |
| * |
| *bit 4: 0, set error_mark after reset/recover |
| * 1, do not set error_mark after reset/recover |
| *bit 5: 0, check total lcu for every picture |
| * 1, do not check total lcu |
| * |
| */ |
| |
| static u32 error_handle_policy; |
| /*static u32 parser_sei_enable = 1;*/ |
| #define MAX_BUF_NUM_NORMAL 12 |
| #define MAX_BUF_NUM_LESS 10 |
| static u32 max_buf_num = MAX_BUF_NUM_NORMAL; |
| #define MAX_BUF_NUM_SAVE_BUF 8 |
| |
| static u32 run_ready_min_buf_num = 2; |
| |
| |
| static DEFINE_MUTEX(vvp9_mutex); |
| #ifndef MULTI_INSTANCE_SUPPORT |
| static struct device *cma_dev; |
| #endif |
| |
| #define HEVC_DEC_STATUS_REG HEVC_ASSIST_SCRATCH_0 |
| #define HEVC_RPM_BUFFER HEVC_ASSIST_SCRATCH_1 |
| #define HEVC_SHORT_TERM_RPS HEVC_ASSIST_SCRATCH_2 |
| #define VP9_ADAPT_PROB_REG HEVC_ASSIST_SCRATCH_3 |
| #define VP9_MMU_MAP_BUFFER HEVC_ASSIST_SCRATCH_4 |
| #define HEVC_PPS_BUFFER HEVC_ASSIST_SCRATCH_5 |
| //#define HEVC_SAO_UP HEVC_ASSIST_SCRATCH_6 |
| #define HEVC_STREAM_SWAP_BUFFER HEVC_ASSIST_SCRATCH_7 |
| #define HEVC_STREAM_SWAP_BUFFER2 HEVC_ASSIST_SCRATCH_8 |
| #define VP9_PROB_SWAP_BUFFER HEVC_ASSIST_SCRATCH_9 |
| #define VP9_COUNT_SWAP_BUFFER HEVC_ASSIST_SCRATCH_A |
| #define VP9_SEG_MAP_BUFFER HEVC_ASSIST_SCRATCH_B |
| //#define HEVC_SCALELUT HEVC_ASSIST_SCRATCH_D |
| #define HEVC_WAIT_FLAG HEVC_ASSIST_SCRATCH_E |
| #define RPM_CMD_REG HEVC_ASSIST_SCRATCH_F |
| #define LMEM_DUMP_ADR HEVC_ASSIST_SCRATCH_F |
| #define HEVC_STREAM_SWAP_TEST HEVC_ASSIST_SCRATCH_L |
| #ifdef MULTI_INSTANCE_SUPPORT |
| #define HEVC_DECODE_COUNT HEVC_ASSIST_SCRATCH_M |
| #define HEVC_DECODE_SIZE HEVC_ASSIST_SCRATCH_N |
| #else |
| #define HEVC_DECODE_PIC_BEGIN_REG HEVC_ASSIST_SCRATCH_M |
| #define HEVC_DECODE_PIC_NUM_REG HEVC_ASSIST_SCRATCH_N |
| #endif |
| #define DEBUG_REG1 HEVC_ASSIST_SCRATCH_G |
| #define DEBUG_REG2 HEVC_ASSIST_SCRATCH_H |
| |
| |
| /* |
| *ucode parser/search control |
| *bit 0: 0, header auto parse; 1, header manual parse |
| *bit 1: 0, auto skip for noneseamless stream; 1, no skip |
| *bit [3:2]: valid when bit1==0; |
| *0, auto skip nal before first vps/sps/pps/idr; |
| *1, auto skip nal before first vps/sps/pps |
| *2, auto skip nal before first vps/sps/pps, |
| * and not decode until the first I slice (with slice address of 0) |
| * |
| *3, auto skip before first I slice (nal_type >=16 && nal_type<=21) |
| *bit [15:4] nal skip count (valid when bit0 == 1 (manual mode) ) |
| *bit [16]: for NAL_UNIT_EOS when bit0 is 0: |
| * 0, send SEARCH_DONE to arm ; 1, do not send SEARCH_DONE to arm |
| *bit [17]: for NAL_SEI when bit0 is 0: |
| * 0, do not parse SEI in ucode; 1, parse SEI in ucode |
| *bit [31:20]: used by ucode for debug purpose |
| */ |
| #define NAL_SEARCH_CTL HEVC_ASSIST_SCRATCH_I |
| /*[31:24] chip feature |
| 31: 0, use MBOX1; 1, use MBOX0 |
| */ |
| #define DECODE_MODE HEVC_ASSIST_SCRATCH_J |
| #define DECODE_STOP_POS HEVC_ASSIST_SCRATCH_K |
| |
| #ifdef MULTI_INSTANCE_SUPPORT |
| #define RPM_BUF_SIZE (0x400 * 2) |