| /* |
| * drivers/amlogic/amports/avs2.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. |
| * |
| */ |
| #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/frame_sync/tsync.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" |
| #include "avs2_global.h" |
| |
| #define MEM_NAME "codec_avs2" |
| /* #include <mach/am_regs.h> */ |
| #include <linux/amlogic/media/utils/vdec_reg.h> |
| #include "../utils/vdec.h" |
| #include "../utils/amvdec.h" |
| |
| #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 <linux/amlogic/tee.h> |
| |
| |
| #define I_ONLY_SUPPORT |
| #define MIX_STREAM_SUPPORT |
| #define G12A_BRINGUP_DEBUG |
| #define CONSTRAIN_MAX_BUF_NUM |
| |
| #include "vavs2.h" |
| #define HEVC_SHIFT_LENGTH_PROTECT 0x313a |
| #define HEVC_MPRED_CTRL9 0x325b |
| #define HEVC_DBLK_CFGD 0x350d |
| |
| |
| #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 |
| |
| |
| /* |
| * AVS2_DEC_STATUS define |
| */ |
| /*internal*/ |
| #define AVS2_DEC_IDLE 0 |
| #define AVS2_SEQUENCE 1 |
| #define AVS2_I_PICTURE 2 |
| #define AVS2_PB_PICTURE 3 |
| #define AVS2_DISCARD_STARTCODE 4 |
| #define AVS2_DISCARD_NAL 4 |
| |
| #define AVS2_SLICE_DECODING 6 |
| |
| #define SWAP_IN_CMD 0x10 |
| #define SWAP_OUT_CMD 0x11 |
| #define SWAP_OUTIN_CMD 0x12 |
| #define SWAP_DONE 0x13 |
| #define SWAP_POST_INIT 0x14 |
| |
| /*head*/ |
| #define AVS2_HEAD_SEQ_READY 0x21 |
| #define AVS2_HEAD_PIC_I_READY 0x22 |
| #define AVS2_HEAD_PIC_PB_READY 0x23 |
| #define AVS2_HEAD_SEQ_END_READY 0x24 |
| #define AVS2_STARTCODE_SEARCH_DONE 0x25 |
| |
| /*pic done*/ |
| #define HEVC_DECPIC_DATA_DONE 0x30 |
| #define HEVC_DECPIC_DATA_ERROR 0x31 |
| #define HEVC_NAL_DECODE_DONE 0x32 |
| #define AVS2_DECODE_BUFEMPTY 0x33 |
| #define AVS2_DECODE_TIMEOUT 0x34 |
| #define AVS2_DECODE_OVER_SIZE 0x35 |
| #define AVS2_EOS 0x36 |
| |
| /*cmd*/ |
| #define AVS2_10B_DISCARD_NAL 0xf0 |
| #define AVS2_SEARCH_NEW_PIC 0xf1 |
| #define AVS2_ACTION_ERROR 0xfe |
| #define HEVC_ACTION_ERROR 0xfe |
| #define AVS2_ACTION_DONE 0xff |
| /*AVS2_DEC_STATUS end*/ |
| |
| |
| #define VF_POOL_SIZE 32 |
| |
| #undef pr_info |
| #define pr_info printk |
| |
| #define DECODE_MODE_SINGLE (0 | (0x80 << 24)) |
| #define DECODE_MODE_MULTI_STREAMBASE (1 | (0x80 << 24)) |
| #define DECODE_MODE_MULTI_FRAMEBASE (2 | (0x80 << 24)) |
| |
| |
| #define VP9_TRIGGER_FRAME_DONE 0x100 |
| #define VP9_TRIGGER_FRAME_ENABLE 0x200 |
| |
| /*#define MV_MEM_UNIT 0x240*/ |
| #define MV_MEM_UNIT 0x200 |
| /*--------------------------------------------------- |
| 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 |
| |
| static unsigned short parser_cmd[PARSER_CMD_NUMBER] = { |
| 0x0401, |
| 0x8401, |
| 0x0800, |
| 0x0402, |
| 0x9002, |
| 0x1423, |
| 0x8CC3, |
| 0x1423, |
| 0x8804, |
| 0x9825, |
| 0x0800, |
| 0x04FE, |
| 0x8406, |
| 0x8411, |
| 0x1800, |
| 0x8408, |
| 0x8409, |
| 0x8C2A, |
| 0x9C2B, |
| 0x1C00, |
| 0x840F, |
| 0x8407, |
| 0x8000, |
| 0x8408, |
| 0x2000, |
| 0xA800, |
| 0x8410, |
| 0x04DE, |
| 0x840C, |
| 0x840D, |
| 0xAC00, |
| 0xA000, |
| 0x08C0, |
| 0x08E0, |
| 0xA40E, |
| 0xFC00, |
| 0x7C00 |
| }; |
| |
| static int32_t g_WqMDefault4x4[16] = { |
| 64, 64, 64, 68, |
| 64, 64, 68, 72, |
| 64, 68, 76, 80, |
| 72, 76, 84, 96 |
| }; |
| |
| |
| static int32_t g_WqMDefault8x8[64] = { |
| 64, 64, 64, 64, 68, 68, 72, 76, |
| 64, 64, 64, 68, 72, 76, 84, 92, |
| 64, 64, 68, 72, 76, 80, 88, 100, |
| 64, 68, 72, 80, 84, 92, 100, 112, |
| 68, 72, 80, 84, 92, 104, 112, 128, |
| 76, 80, 84, 92, 104, 116, 132, 152, |
| 96, 100, 104, 116, 124, 140, 164, 188, |
| 104, 108, 116, 128, 152, 172, 192, 216 |
| }; |
| /*#define HEVC_PIC_STRUCT_SUPPORT*/ |
| /* to remove, fix build error */ |
| |
| /*#define CODEC_MM_FLAGS_FOR_VDECODER 0*/ |
| |
| #define MULTI_INSTANCE_SUPPORT |
| /* #define ERROR_HANDLE_DEBUG */ |
| |
| #ifndef STAT_KTHREAD |
| #define STAT_KTHREAD 0x40 |
| #endif |
| |
| #ifdef MULTI_INSTANCE_SUPPORT |
| #define MAX_DECODE_INSTANCE_NUM 12 |
| #define MULTI_DRIVER_NAME "ammvdec_avs2" |
| |
| #define lock_buffer(dec, flags) \ |
| spin_lock_irqsave(&dec->buffer_lock, flags) |
| |
| #define unlock_buffer(dec, flags) \ |
| spin_unlock_irqrestore(&dec->buffer_lock, flags) |
| |
| 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]; |
| |
| #ifdef G12A_BRINGUP_DEBUG |
| static u32 decode_timeout_val = 200; |
| #else |
| static u32 decode_timeout_val = 200; |
| #endif |
| static int start_decode_buf_level = 0x8000; |
| #ifdef AVS2_10B_MMU |
| static u32 work_buf_size; /* = 24 * 1024 * 1024*/; |
| #else |
| static u32 work_buf_size = 32 * 1024 * 1024; |
| #endif |
| |
| static u32 mv_buf_margin; |
| static int pre_decode_buf_level = 0x1000; |
| static u32 again_threshold; |
| |
| |
| /* 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; |
| static u32 without_display_mode; |
| |
| static u32 mv_buf_dynamic_alloc; |
| |
| #define DRIVER_NAME "amvdec_avs2" |
| #define DRIVER_HEADER_NAME "amvdec_avs2_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 AVS2Decoder_s; |
| static int vavs2_vf_states(struct vframe_states *states, void *); |
| static struct vframe_s *vavs2_vf_peek(void *); |
| static struct vframe_s *vavs2_vf_get(void *); |
| static void vavs2_vf_put(struct vframe_s *, void *); |
| static int vavs2_event_cb(int type, void *data, void *private_data); |
| static void set_vframe(struct AVS2Decoder_s *dec, |
| struct vframe_s *vf, struct avs2_frame_s *pic, u8 dummy); |
| |
| static int vavs2_stop(struct AVS2Decoder_s *dec); |
| static s32 vavs2_init(struct vdec_s *vdec); |
| static void vavs2_prot_init(struct AVS2Decoder_s *dec); |
| static int vavs2_local_init(struct AVS2Decoder_s *dec); |
| static void vavs2_put_timer_func(unsigned long arg); |
| static void dump_data(struct AVS2Decoder_s *dec, int size); |
| static unsigned char get_data_check_sum |
| (struct AVS2Decoder_s *dec, int size); |
| static void dump_pic_list(struct AVS2Decoder_s *dec); |
| |
| static const char vavs2_dec_id[] = "vavs2-dev"; |
| |
| #define PROVIDER_NAME "decoder.avs2" |
| #define MULTI_INSTANCE_PROVIDER_NAME "vdec.avs2" |
| |
| static const struct vframe_operations_s vavs2_vf_provider = { |
| .peek = vavs2_vf_peek, |
| .get = vavs2_vf_get, |
| .put = vavs2_vf_put, |
| .event_cb = vavs2_event_cb, |
| .vf_states = vavs2_vf_states, |
| }; |
| |
| static struct vframe_provider_s vavs2_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 pts_unstable; |
| static u32 on_no_keyframe_skiped; |
| |
| static u32 force_video_signal_type; |
| static u32 enable_force_video_signal_type; |
| #define VIDEO_SIGNAL_TYPE_AVAILABLE_MASK 0x20000000 |
| |
| static const char * const video_format_names[] = { |
| "component", "PAL", "NTSC", "SECAM", |
| "MAC", "unspecified", "Reserved", "Reserved" |
| }; |
| |
| 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 |
| } |
| |
| enum vpx_bit_depth_t { |
| AVS2_BITS_8 = 8, /**< 8 bits */ |
| AVS2_BITS_10 = 10, /**< 10 bits */ |
| AVS2_BITS_12 = 12, /**< 12 bits */ |
| }; |
| |
| /*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; |
| } /*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 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*/ |
| |
| #ifdef AVS2_10B_NV21 |
| #define MEM_MAP_MODE 2 /* 0:linear 1:32x32 2:64x32*/ |
| #else |
| #define MEM_MAP_MODE 0 /* 0:linear 1:32x32 2:64x32*/ |
| #endif |
| |
| #ifdef AVS2_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 AVS2_DBG_BUFMGR 0x01 |
| #define AVS2_DBG_BUFMGR_MORE 0x02 |
| #define AVS2_DBG_BUFMGR_DETAIL 0x04 |
| #define AVS2_DBG_IRQ_EVENT 0x08 |
| #define AVS2_DBG_OUT_PTS 0x10 |
| #define AVS2_DBG_PRINT_SOURCE_LINE 0x20 |
| #define AVS2_DBG_PRINT_PARAM 0x40 |
| #define AVS2_DBG_PRINT_PIC_LIST 0x80 |
| #define AVS2_DBG_SEND_PARAM_WITH_REG 0x100 |
| #define AVS2_DBG_MERGE 0x200 |
| #define AVS2_DBG_DBG_LF_PRINT 0x400 |
| #define AVS2_DBG_REG 0x800 |
| #define AVS2_DBG_PIC_LEAK 0x1000 |
| #define AVS2_DBG_PIC_LEAK_WAIT 0x2000 |
| #define AVS2_DBG_HDR_INFO 0x4000 |
| #define AVS2_DBG_DIS_LOC_ERROR_PROC 0x10000 |
| #define AVS2_DBG_DIS_SYS_ERROR_PROC 0x20000 |
| #define AVS2_DBG_DUMP_PIC_LIST 0x40000 |
| #define AVS2_DBG_TRIG_SLICE_SEGMENT_PROC 0x80000 |
| #define AVS2_DBG_FORCE_UNCOMPRESS 0x100000 |
| #define AVS2_DBG_LOAD_UCODE_FROM_FILE 0x200000 |
| #define AVS2_DBG_FORCE_SEND_AGAIN 0x400000 |
| #define AVS2_DBG_DUMP_DATA 0x800000 |
| #define AVS2_DBG_DUMP_LMEM_BUF 0x1000000 |
| #define AVS2_DBG_DUMP_RPM_BUF 0x2000000 |
| #define AVS2_DBG_CACHE 0x4000000 |
| #define IGNORE_PARAM_FROM_CONFIG 0x8000000 |
| /*MULTI_INSTANCE_SUPPORT*/ |
| #define PRINT_FLAG_ERROR 0 |
| #define PRINT_FLAG_VDEC_STATUS 0x20000000 |
| #define PRINT_FLAG_VDEC_DETAIL 0x40000000 |
| #define PRINT_FLAG_VDEC_DATA 0x80000000 |
| |
| #define PRINT_LINE() \ |
| do { \ |
| if (debug & AVS2_DBG_PRINT_SOURCE_LINE)\ |
| pr_info("%s line %d\n", __func__, __LINE__);\ |
| } while (0) |
| |
| static u32 debug; |
| |
| static u32 debug_again; |
| |
| bool is_avs2_print_param(void) |
| { |
| bool ret = false; |
| if (debug & AVS2_DBG_PRINT_PARAM) |
| ret = true; |
| return ret; |
| } |
| |
| bool is_avs2_print_bufmgr_detail(void) |
| { |
| bool ret = false; |
| if (debug & AVS2_DBG_BUFMGR_DETAIL) |
| ret = true; |
| return ret; |
| } |
| static bool is_reset; |
| /*for debug*/ |
| static u32 force_bufspec; |
| /* |
| 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 force_disp_pic_index; |
| |
| #define DEBUG_REG |
| #ifdef DEBUG_REG |
| static void WRITE_VREG_DBG2(unsigned adr, unsigned val) |
| { |
| if (debug & AVS2_DBG_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 |
| |
| |
| //#ifdef AVS2_10B_MMU |
| //#define MMU_COMPRESS_HEADER_SIZE 0x48000 |
| //#define MMU_COMPRESS_8K_HEADER_SIZE 0x48000*4 |
| //#endif |
| #define MMU_COMPRESS_HEADER_SIZE_1080P 0x10000 |
| #define MMU_COMPRESS_HEADER_SIZE_4K 0x48000 |
| #define MMU_COMPRESS_HEADER_SIZE_8K 0x120000 |
| |
| #define INVALID_IDX -1 /* Invalid buffer index.*/ |
| |
| |
| #define FRAME_BUFFERS (AVS2_MAX_BUFFER_NUM) |
| #define HEADER_FRAME_BUFFERS (FRAME_BUFFERS) |
| #define MAX_BUF_NUM (FRAME_BUFFERS) |
| |
| #define FRAME_CONTEXTS_LOG2 2 |
| #define FRAME_CONTEXTS (1 << FRAME_CONTEXTS_LOG2) |
| /*buffer + header buffer + workspace*/ |
| #undef MV_USE_FIXED_BUF |
| #ifdef MV_USE_FIXED_BUF |
| #define MAX_BMMU_BUFFER_NUM ((FRAME_BUFFERS + HEADER_FRAME_BUFFERS + 1)+1) |
| #define VF_BUFFER_IDX(n) (n) |
| #define HEADER_BUFFER_IDX(n) (FRAME_BUFFERS + n+1) |
| #define WORK_SPACE_BUF_ID (FRAME_BUFFERS + HEADER_FRAME_BUFFERS+1) |
| #else |
| #define MAX_BMMU_BUFFER_NUM (((FRAME_BUFFERS*2)+HEADER_FRAME_BUFFERS+1)+1) |
| #define VF_BUFFER_IDX(n) (n) |
| #define HEADER_BUFFER_IDX(n) (FRAME_BUFFERS + n+1) |
| #define MV_BUFFER_IDX(n) ((FRAME_BUFFERS * 2) + n+1) |
| #define WORK_SPACE_BUF_ID ((FRAME_BUFFERS * 2) + HEADER_FRAME_BUFFERS+1) |
| #endif |
| |
| #define CO_MV_BUF_SIZE_1080P 0x3fc00 |
| #define CO_MV_BUF_SIZE_4K 0x120000 |
| #define CO_MV_BUF_SIZE_8K 0x480000 |
| /* |
| static void set_canvas(struct AVS2Decoder_s *dec, |
| struct avs2_frame_s *pic); |
| int avs2_prepare_display_buf(struct AVS2Decoder_s *dec, |
| int pos); |
| */ |
| |
| |
| struct buff_s { |
| u32 buf_start; |
| u32 buf_size; |
| u32 buf_end; |
| }; |
| |
| 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 rcs; |
| 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 dblk_data2; |
| #ifdef AVS2_10B_MMU |
| struct buff_s mmu_vbh; |
| struct buff_s cm_header; |
| #endif |
| struct buff_s mpred_above; |
| #ifdef MV_USE_FIXED_BUF |
| struct buff_s mpred_mv; |
| #endif |
| struct buff_s rpm; |
| struct buff_s lmem; |
| }; |
| |
| #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 |
| |
| static void avs2_work(struct work_struct *work); |
| struct loop_filter_info_n; |
| struct loopfilter; |
| struct segmentation; |
| |
| struct AVS2Decoder_s { |
| int pic_list_init_flag; |
| unsigned char index; |
| spinlock_t buffer_lock; |
| 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; |
| 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 double_write_mode; |
| |
| unsigned char m_ins_flag; |
| char *provider_name; |
| int frame_count; |
| u32 stat; |
| struct timer_list timer; |
| u32 frame_dur; |
| u32 frame_ar; |
| u32 vavs2_ratio; |
| int fatal_error; |
| uint8_t init_flag; |
| uint8_t first_sc_checked; |
| uint8_t process_busy; |
| #define PROC_STATE_INIT 0 |
| #define PROC_STATE_HEAD_DONE 1 |
| #define PROC_STATE_DECODING 2 |
| #define PROC_STATE_HEAD_AGAIN 3 |
| #define PROC_STATE_DECODE_AGAIN 4 |
| #define PROC_STATE_TEST1 5 |
| uint8_t process_state; |
| u32 ucode_pause_pos; |
| |
| int show_frame_num; |
| #ifndef AVS2_10B_MMU |
| struct buff_s mc_buf_spec; |
| #endif |
| struct dec_sysinfo vavs2_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; |
| |
| #if 1 |
| /*AVS2_10B_MMU*/ |
| void *frame_mmu_map_addr; |
| dma_addr_t frame_mmu_map_phy_addr; |
| #endif |
| unsigned int use_cma_flag; |
| |
| struct BUF_s m_BUF[MAX_BUF_NUM]; |
| struct MVBUF_s m_mv_BUF[MAX_BUF_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; |
| unsigned int losless_comp_body_size; |
| |
| u32 video_signal_type; |
| u32 video_ori_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 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; |
| |
| /**/ |
| int refresh_frame_flags; |
| uint8_t hold_ref_buf; |
| struct BuffInfo_s *work_space_buf; |
| #ifndef AVS2_10B_MMU |
| struct buff_s *mc_buf; |
| #endif |
| unsigned int frame_width; |
| unsigned int frame_height; |
| |
| unsigned short *rpm_ptr; |
| int init_pic_w; |
| int init_pic_h; |
| |
| int slice_type; |
| |
| int decode_idx; |
| int slice_idx; |
| uint8_t wait_buf; |
| uint8_t error_flag; |
| unsigned int bufmgr_error_count; |
| |
| /* bit 0, for decoding; bit 1, for displaying */ |
| uint8_t ignore_bufmgr_error; |
| uint8_t skip_PB_before_I; |
| int PB_skip_mode; |
| int PB_skip_count_after_decoding; |
| /*hw*/ |
| |
| /**/ |
| struct vdec_info *gvs; |
| |
| |
| unsigned int dec_status; |
| u32 last_put_idx; |
| int new_frame_displayed; |
| void *mmu_box; |
| void *bmmu_box; |
| struct vframe_master_display_colour_s vf_dp; |
| struct firmware_s *fw; |
| #ifdef AVS2_10B_MMU |
| int cur_fb_idx_mmu; |
| long used_4k_num; |
| #endif |
| struct avs2_decoder avs2_dec; |
| #define ALF_NUM_BIT_SHIFT 6 |
| #define NO_VAR_BINS 16 |
| int32_t m_filterCoeffSym[16][9]; |
| int32_t m_varIndTab[NO_VAR_BINS]; |
| |
| struct vframe_s vframe_dummy; |
| /* start_decoding_flag, |
| bit 0, SEQ ready |
| bit 1, I ready |
| */ |
| unsigned char start_decoding_flag; |
| uint32_t mpred_abv_start_addr; |
| uint32_t mpred_abv_start_addr_bak; |
| u8 next_again_flag; |
| u32 pre_parser_wr_ptr; |
| int need_cache_size; |
| u64 sc_start_time; |
| #ifdef I_ONLY_SUPPORT |
| u32 i_only; |
| #endif |
| int frameinfo_enable; |
| struct vframe_qos_s vframe_qos; |
| u32 dynamic_buf_margin; |
| int sidebind_type; |
| int sidebind_channel_id; |
| char vdec_name[32]; |
| char pts_name[32]; |
| char new_q_name[32]; |
| char disp_q_name[32]; |
| }; |
| |
| static int compute_losless_comp_body_size( |
| struct AVS2Decoder_s *dec, int width, int height, |
| uint8_t is_bit_depth_10); |
| |
| static int avs2_print(struct AVS2Decoder_s *dec, |
| int flag, const char *fmt, ...) |
| { |
| #define HEVC_PRINT_BUF 256 |
| unsigned char buf[HEVC_PRINT_BUF]; |
| int len = 0; |
| if (dec == NULL || |
| (flag == 0) || |
| (debug & flag)) { |
| va_list args; |
| va_start(args, fmt); |
| if (dec) |
| len = sprintf(buf, "[%d]", dec->index); |
| vsnprintf(buf + len, HEVC_PRINT_BUF - len, fmt, args); |
| pr_info("%s", buf); |
| va_end(args); |
| } |
| return 0; |
| } |
| |
| static int avs2_print_cont(struct AVS2Decoder_s *dec, |
| int flag, const char *fmt, ...) |
| { |
| unsigned char buf[HEVC_PRINT_BUF]; |
| int len = 0; |
| if (dec == NULL || |
| (flag == 0) || |
| (debug & flag)) { |
| va_list args; |
| va_start(args, fmt); |
| vsnprintf(buf + len, HEVC_PRINT_BUF - len, fmt, args); |
| pr_info("%s", buf); |
| va_end(args); |
| } |
| return 0; |
| } |
| |
| #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 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)) |
| |
| static int get_frame_mmu_map_size(struct AVS2Decoder_s *dec) |
| { |
| if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && |
| (IS_8K_SIZE(dec->init_pic_w, dec->init_pic_h))) |
| return (MAX_FRAME_8K_NUM * 4); |
| return (MAX_FRAME_4K_NUM * 4); |
| } |
| |
| static int get_compress_header_size(struct AVS2Decoder_s *dec) |
| { |
| if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && |
| (IS_8K_SIZE(dec->init_pic_w, dec->init_pic_h))) |
| return MMU_COMPRESS_HEADER_SIZE_8K; |
| else if (IS_4K_SIZE(dec->init_pic_w, dec->init_pic_h)) |
| return MMU_COMPRESS_HEADER_SIZE_4K; |
| return MMU_COMPRESS_HEADER_SIZE_1080P; |
| } |
| |
| static void reset_process_time(struct AVS2Decoder_s *dec) |
| { |
| if (dec->start_process_time) { |
| unsigned process_time = |
| 1000 * (jiffies - dec->start_process_time) / HZ; |
| dec->start_process_time = 0; |
| if (process_time > max_process_time[dec->index]) |
| max_process_time[dec->index] = process_time; |
| } |
| } |
| |
| static void start_process_time(struct AVS2Decoder_s *dec) |
| { |
| dec->start_process_time = jiffies; |
| dec->decode_timeout_count = 0; |
| dec->last_lcu_idx = 0; |
| } |
| |
| static void update_decoded_pic(struct AVS2Decoder_s *dec); |
| |
| static void timeout_process(struct AVS2Decoder_s *dec) |
| { |
| struct avs2_decoder *avs2_dec = &dec->avs2_dec; |
| struct avs2_frame_s *cur_pic = avs2_dec->hc.cur_pic; |
| dec->timeout_num++; |
| amhevc_stop(); |
| avs2_print(dec, |
| 0, "%s decoder timeout\n", __func__); |
| if (cur_pic) |
| cur_pic->error_mark = 1; |
| dec->dec_result = DEC_RESULT_DONE; |
| update_decoded_pic(dec); |
| reset_process_time(dec); |
| vdec_schedule_work(&dec->work); |
| } |
| |
| static u32 get_valid_double_write_mode(struct AVS2Decoder_s *dec) |
| { |
| return (dec->m_ins_flag && |
| ((double_write_mode & 0x80000000) == 0)) ? |
| dec->double_write_mode : |
| (double_write_mode & 0x7fffffff); |
| } |
| |
| static int get_double_write_mode(struct AVS2Decoder_s *dec) |
| { |
| u32 valid_dw_mode = get_valid_double_write_mode(dec); |
| int w = dec->avs2_dec.img.width; |
| int h = dec->avs2_dec.img.height; |
| u32 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; |
| } |
| |
| /* for double write buf alloc */ |
| static int get_double_write_mode_init(struct AVS2Decoder_s *dec) |
| { |
| u32 valid_dw_mode = get_valid_double_write_mode(dec); |
| u32 dw; |
| int w = dec->init_pic_w; |
| int h = dec->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; |
| } |
| |
| static int get_double_write_ratio(struct AVS2Decoder_s *dec, |
| 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 |
| #ifdef AVS2_10B_MMU |
| int avs2_alloc_mmu( |
| struct AVS2Decoder_s *dec, |
| 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 == AVS2_BITS_10); |
| int picture_size; |
| int cur_mmu_4k_number, max_frame_num; |
| #ifdef DYNAMIC_ALLOC_HEAD |
| unsigned long buf_addr; |
| struct avs2_frame_s *pic = dec->avs2_dec.hc.cur_pic; |
| if (pic->header_adr == 0) { |
| if (decoder_bmmu_box_alloc_buf_phy |
| (dec->bmmu_box, |
| HEADER_BUFFER_IDX(cur_buf_idx), |
| get_compress_header_size(dec), |
| DRIVER_HEADER_NAME, |
| &buf_addr) < 0){ |
| avs2_print(dec, 0, |
| "%s malloc compress header failed %d\n", |
| DRIVER_HEADER_NAME, cur_buf_idx); |
| dec->fatal_error |= DECODER_FATAL_ERROR_NO_MEM; |
| return -1; |
| } else |
| pic->header_adr = buf_addr; |
| } |
| #endif |
| |
| picture_size = compute_losless_comp_body_size( |
| dec, 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( |
| dec->mmu_box, |
| cur_buf_idx, |
| cur_mmu_4k_number, |
| mmu_index_adr); |
| } |
| #endif |
| |
| #if 0 |
| /*ndef MV_USE_FIXED_BUF*/ |
| static void dealloc_mv_bufs(struct AVS2Decoder_s *dec) |
| { |
| int i; |
| for (i = 0; i < FRAME_BUFFERS; i++) { |
| if (dec->m_mv_BUF[i].start_adr) { |
| if (debug) |
| pr_info( |
| "dealloc mv buf(%d) adr %ld size 0x%x used_flag %d\n", |
| i, dec->m_mv_BUF[i].start_adr, |
| dec->m_mv_BUF[i].size, |
| dec->m_mv_BUF[i].used_flag); |
| decoder_bmmu_box_free_idx( |
| dec->bmmu_box, |
| MV_BUFFER_IDX(i)); |
| dec->m_mv_BUF[i].start_adr = 0; |
| dec->m_mv_BUF[i].size = 0; |
| dec->m_mv_BUF[i].used_flag = 0; |
| } |
| } |
| } |
| |
| static int alloc_mv_buf(struct AVS2Decoder_s *dec, |
| int i, int size) |
| { |
| int ret = 0; |
| if (decoder_bmmu_box_alloc_buf_phy |
| (dec->bmmu_box, |
| MV_BUFFER_IDX(i), size, |
| DRIVER_NAME, |
| &dec->m_mv_BUF[i].start_adr) < 0) { |
| dec->m_mv_BUF[i].start_adr = 0; |
| ret = -1; |
| } else { |
| dec->m_mv_BUF[i].size = size; |
| dec->m_mv_BUF[i].used_flag = 0; |
| ret = 0; |
| if (debug) { |
| pr_info( |
| "MV Buffer %d: start_adr %p size %x\n", |
| i, |
| (void *)dec->m_mv_BUF[i].start_adr, |
| dec->m_mv_BUF[i].size); |
| } |
| } |
| return ret; |
| } |
| |
| static int init_mv_buf_list(struct AVS2Decoder_s *dec) |
| { |
| int i; |
| int ret = 0; |
| int count = FRAME_BUFFERS; |
| int pic_width = dec->init_pic_w; |
| int pic_height = dec->init_pic_h; |
| 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 = ((lcu_total * MV_MEM_UNIT) + 0xffff) & |
| (~0xffff); |
| if (mv_buf_margin > 0) |
| count = dec->avs2_dec.ref_maxbuffer + mv_buf_margin; |
| for (i = 0; i < count; i++) { |
| if (alloc_mv_buf(dec, i, size) < 0) { |
| ret = -1; |
| break; |
| } |
| } |
| return ret; |
| } |
| #if 0 |
| |
| static int get_mv_buf(struct AVS2Decoder_s *dec, |
| struct avs2_frame_s *pic) |
| { |
| int i; |
| int ret = -1; |
| for (i = 0; i < FRAME_BUFFERS; i++) { |
| if (dec->m_mv_BUF[i].start_adr && |
| dec->m_mv_BUF[i].used_flag == 0) { |
| dec->m_mv_BUF[i].used_flag = 1; |
| ret = i; |
| break; |
| } |
| } |
| |
| if (ret >= 0) { |
| pic->mv_buf_index = ret; |
| pic->mpred_mv_wr_start_addr = |
| (dec->m_mv_BUF[ret].start_adr + 0xffff) & |
| (~0xffff); |
| if (debug & AVS2_DBG_BUFMGR_MORE) |
| pr_info( |
| "%s => %d (%d) size 0x%x\n", |
| __func__, ret, |
| pic->mpred_mv_wr_start_addr, |
| dec->m_mv_BUF[ret].size); |
| } else { |
| pr_info( |
| "%s: Error, mv buf is not enough\n", |
| __func__); |
| } |
| return ret; |
| } |
| |
| static void put_mv_buf(struct AVS2Decoder_s *dec, |
| struct avs2_frame_s *pic) |
| { |
| int i = pic->mv_buf_index; |
| if (i >= FRAME_BUFFERS) { |
| if (debug & AVS2_DBG_BUFMGR_MORE) |
| pr_info( |
| "%s: index %d beyond range\n", |
| __func__, i); |
| return; |
| } |
| if (debug & AVS2_DBG_BUFMGR_MORE) |
| pr_info( |
| "%s(%d): used_flag(%d)\n", |
| __func__, i, |
| dec->m_mv_BUF[i].used_flag); |
| |
| pic->mv_buf_index = -1; |
| if (dec->m_mv_BUF[i].start_adr && |
| dec->m_mv_BUF[i].used_flag) |
| dec->m_mv_BUF[i].used_flag = 0; |
| } |
| |
| static void put_un_used_mv_bufs(struct AVS2Decoder_s *dec) |
| { |
| struct VP9_Common_s *const cm = &dec->common; |
| struct RefCntBuffer_s *const frame_bufs = cm->buffer_pool->frame_bufs; |
| int i; |
| for (i = 0; i < dec->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(dec, &frame_bufs[i].buf); |
| } |
| } |
| #endif |
| |
| #endif |
| |
| static int get_free_buf_count(struct AVS2Decoder_s *dec) |
| { |
| struct avs2_decoder *avs2_dec = &dec->avs2_dec; |
| int i; |
| int count = 0; |
| for (i = 0; i < avs2_dec->ref_maxbuffer; i++) { |
| if ((avs2_dec->fref[i]->imgcoi_ref < -256 |
| #if 0 |
| || abs(avs2_dec->fref[i]-> |
| imgtr_fwRefDistance - img->tr) >= 128 |
| #endif |
| ) && avs2_dec->fref[i]->is_output == -1 |
| && avs2_dec->fref[i]->bg_flag == 0 |
| #ifndef NO_DISPLAY |
| && avs2_dec->fref[i]->vf_ref == 0 |
| && avs2_dec->fref[i]->to_prepare_disp == 0 |
| #endif |
| ) { |
| count++; |
| } |
| } |
| |
| return count; |
| } |
| |
| #ifdef CONSTRAIN_MAX_BUF_NUM |
| static int get_vf_ref_only_buf_count(struct AVS2Decoder_s *dec) |
| { |
| struct avs2_decoder *avs2_dec = &dec->avs2_dec; |
| int i; |
| int count = 0; |
| for (i = 0; i < avs2_dec->ref_maxbuffer; i++) { |
| if ((avs2_dec->fref[i]->imgcoi_ref < -256 |
| #if 0 |
| || abs(avs2_dec->fref[i]-> |
| imgtr_fwRefDistance - img->tr) >= 128 |
| #endif |
| ) && avs2_dec->fref[i]->is_output == -1 |
| && avs2_dec->fref[i]->bg_flag == 0 |
| #ifndef NO_DISPLAY |
| && avs2_dec->fref[i]->vf_ref > 0 |
| && avs2_dec->fref[i]->to_prepare_disp == 0 |
| #endif |
| ) { |
| count++; |
| } |
| } |
| |
| return count; |
| } |
| |
| static int get_used_buf_count(struct AVS2Decoder_s *dec) |
| { |
| struct avs2_decoder *avs2_dec = &dec->avs2_dec; |
| int i; |
| int count = 0; |
| for (i = 0; i < avs2_dec->ref_maxbuffer; i++) { |
| if ((avs2_dec->fref[i]->imgcoi_ref >= -256 |
| #if 0 |
| || abs(avs2_dec->fref[i]-> |
| imgtr_fwRefDistance - img->tr) >= 128 |
| #endif |
| ) || avs2_dec->fref[i]->is_output != -1 |
| || avs2_dec->fref[i]->bg_flag != 0 |
| #ifndef NO_DISPLAY |
| || avs2_dec->fref[i]->vf_ref != 0 |
| || avs2_dec->fref[i]->to_prepare_disp != 0 |
| #endif |
| ) { |
| count++; |
| } |
| } |
| |
| return count; |
| } |
| #endif |
| |
| int avs2_bufmgr_init(struct AVS2Decoder_s *dec, struct BuffInfo_s *buf_spec_i, |
| struct buff_s *mc_buf_i) { |
| |
| dec->frame_count = 0; |
| #ifdef AVS2_10B_MMU |
| dec->used_4k_num = -1; |
| dec->cur_fb_idx_mmu = INVALID_IDX; |
| #endif |
| |
| |
| /* private init */ |
| dec->work_space_buf = buf_spec_i; |
| #ifndef AVS2_10B_MMU |
| dec->mc_buf = mc_buf_i; |
| #endif |
| dec->rpm_addr = NULL; |
| dec->lmem_addr = NULL; |
| |
| dec->use_cma_flag = 0; |
| dec->decode_idx = 0; |
| dec->slice_idx = 0; |
| /*int m_uiMaxCUWidth = 1<<7;*/ |
| /*int m_uiMaxCUHeight = 1<<7;*/ |
| dec->wait_buf = 0; |
| dec->error_flag = 0; |
| dec->skip_PB_before_I = 0; |
| |
| dec->pts_mode = PTS_NORMAL; |
| dec->last_pts = 0; |
| dec->last_lookup_pts = 0; |
| dec->last_pts_us64 = 0; |
| dec->last_lookup_pts_us64 = 0; |
| dec->shift_byte_count = 0; |
| dec->shift_byte_count_lo = 0; |
| dec->shift_byte_count_hi = 0; |
| dec->pts_mode_switching_count = 0; |
| dec->pts_mode_recovery_count = 0; |
| |
| dec->buf_num = 0; |
| |
| dec->bufmgr_error_count = 0; |
| return 0; |
| } |
| |
| |
| |
| #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*/ |
| |
| static u32 mem_map_mode; /* 0:linear 1:32x32 2:64x32 ; m8baby test1902 */ |
| static u32 enable_mem_saving = 1; |
| static u32 force_w_h; |
| |
| static u32 force_fps; |
| |
| |
| const u32 avs2_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 dynamic_buf_num_margin; |
| #else |
| static u32 buf_alloc_width; |
| static u32 buf_alloc_height; |
| static u32 dynamic_buf_num_margin = 7; |
| #endif |
| #ifdef CONSTRAIN_MAX_BUF_NUM |
| static u32 run_ready_max_vf_only_num; |
| static u32 run_ready_display_q_num; |
| /*0: not check |
| 0xff: avs2_dec.ref_maxbuffer |
| */ |
| static u32 run_ready_max_buf_num = 0xff; |
| #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 max_decoding_time; |
| /* |
| error handling |
| */ |
| /*error_handle_policy: |
| bit 0: search seq again if buffer mgr error occur |
| (buffer mgr error count need big than |
| re_search_seq_threshold) |
| bit 1: 1, display from I picture; |
| 0, display from any correct pic |
| */ |
| |
| static u32 error_handle_policy = 1; |
| /* |
| re_search_seq_threshold: |
| bit 7~0: buffer mgr error research seq count |
| bit 15~8: frame count threshold |
| */ |
| static u32 re_search_seq_threshold = 0x800; /*0x8;*/ |
| /*static u32 parser_sei_enable = 1;*/ |
| |
| static u32 max_buf_num = (REF_BUFFER + 1); |
| |
| static u32 run_ready_min_buf_num = 2; |
| |
| static DEFINE_MUTEX(vavs2_mutex); |
| |
| #define HEVC_DEC_STATUS_REG HEVC_ASSIST_SCRATCH_0 |
| #define HEVC_RPM_BUFFER HEVC_ASSIST_SCRATCH_1 |
| #define AVS2_ALF_SWAP_BUFFER HEVC_ASSIST_SCRATCH_2 |
| #define HEVC_RCS_BUFFER HEVC_ASSIST_SCRATCH_3 |
| #define HEVC_SPS_BUFFER HEVC_ASSIST_SCRATCH_4 |
| #define HEVC_PPS_BUFFER HEVC_ASSIST_SCRATCH_5 |
| //#define HEVC_SAO_UP HEVC_ASSIST_SCRATCH_6 |
| #ifdef AVS2_10B_MMU |
| #define AVS2_MMU_MAP_BUFFER HEVC_ASSIST_SCRATCH_7 |
| #else |
| #define HEVC_STREAM_SWAP_BUFFER HEVC_ASSIST_SCRATCH_7 |
| #endif |
| #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_9 |
| #define HEVC_STREAM_SWAP_TEST HEVC_ASSIST_SCRATCH_L |
| /*!!!*/ |
| #define HEVC_DECODE_COUNT HEVC_ASSIST_SCRATCH_M |
| #define HEVC_DECODE_SIZE HEVC_ASSIST_SCRATCH_N |
| #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 |
| /*DECODE_MODE: set before start decoder |
| bit 7~0: decode mode |
| bit 23~16: start_decoding_flag |
| bit [0] - SEQ_ready |
| bit [2:1] - I Picture Count |
| bit 31~24: chip feature |
| */ |
| #define DECODE_MODE HEVC_ASSIST_SCRATCH_J |
| #define DECODE_STOP_POS HEVC_ASSIST_SCRATCH_K |
| /*read only*/ |
| #define CUR_NAL_UNIT_TYPE HEVC_ASSIST_SCRATCH_J |
| |
| #define RPM_BUF_SIZE (0x600 * 2) |
| #define LMEM_BUF_SIZE (0x600 * 2) |
| |
| /*mmu_vbh buf is used by HEVC_SAO_MMU_VH0_ADDR, HEVC_SAO_MMU_VH1_ADDR*/ |
| #define VBH_BUF_SIZE_1080P 0x3000 |
| #define VBH_BUF_SIZE_4K 0x5000 |
| #define VBH_BUF_SIZE_8K 0xa000 |
| #define VBH_BUF_SIZE(bufspec) (bufspec->mmu_vbh.buf_size / 2) |
| /*mmu_vbh_dw buf is used by HEVC_SAO_MMU_VH0_ADDR2,HEVC_SAO_MMU_VH1_ADDR2, |
| HEVC_DW_VH0_ADDDR, HEVC_DW_VH1_ADDDR*/ |
| #define DW_VBH_BUF_SIZE_1080P (VBH_BUF_SIZE_1080P * 2) |
| #define DW_VBH_BUF_SIZE_4K (VBH_BUF_SIZE_4K * 2) |
| #define DW_VBH_BUF_SIZE_8K (VBH_BUF_SIZE_8K * 2) |
| #define DW_VBH_BUF_SIZE(bufspec) (bufspec->mmu_vbh_dw.buf_size / 4) |
| |
| #define WORK_BUF_SPEC_NUM 3 |
| static struct BuffInfo_s amvavs2_workbuff_spec[WORK_BUF_SPEC_NUM] = { |
| { |
| /* 8M bytes */ |
| .max_width = 1920, |
| .max_height = 1088, |
| .ipp = { |
| /* IPP work space calculation : |
| 4096 * (Y+CbCr+Flags) = 12k, round to 16k */ |
| .buf_size = 0x1e00, |
| }, |
| .sao_abv = { |
| .buf_size = 0, |
| }, |
| .sao_vb = { |
| .buf_size = 0, |
| }, |
| .short_term_rps = { |
| /* SHORT_TERM_RPS - Max 64 set, 16 entry every set, |
| total 64x16x2 = 2048 bytes (0x800) */ |
| .buf_size = 0x800, |
| }, |
| .rcs = { |
| /* RCS STORE AREA - Max 32 RCS, each has 32 bytes, |
| total 0x0400 bytes */ |
| .buf_size = 0x400, |
| }, |
| .sps = { |
| /* SPS STORE AREA - Max 16 SPS, each has 0x80 bytes, |
| total 0x0800 bytes*/ |
| .buf_size = 0x800, |
| }, |
| .pps = { |
| /*PPS STORE AREA - Max 64 PPS, each has 0x80 bytes, |
| total 0x2000 bytes*/ |
| .buf_size = 0x2000, |
| }, |
| .sao_up = { |
| /* SAO UP STORE AREA - Max 640(10240/16) LCU, |
| each has 16 bytes total 0x2800 bytes */ |
| .buf_size = 0, |
| }, |
| .swap_buf = { |
| /* 256cyclex64bit = 2K bytes 0x800 |
| (only 144 cycles valid) */ |
| .buf_size = 0x800, |
| }, |
| .swap_buf2 = { |
| .buf_size = 0x800, |
| }, |
| .scalelut = { |
| /* support up to 32 SCALELUT 1024x32 = |
| 32Kbytes (0x8000) */ |
| .buf_size = 0, |
| }, |
| .dblk_para = { |
| /* DBLK -> Max 256(4096/16) LCU, |
| each para 1024bytes(total:0x40000), |
| data 1024bytes(total:0x40000)*/ |
| .buf_size = 0x3d00, //0x3c80, |
| }, |
| .dblk_data = { |
| .buf_size = 0x62800, |
| }, |
| .dblk_data2 = { |
| .buf_size = 0x62800, |
| }, |
| #ifdef AVS2_10B_MMU |
| .mmu_vbh = { |
| .buf_size = VBH_BUF_SIZE_1080P, /*2*16*(more than 2304)/4, 4K*/ |
| }, |
| #if 0 |
| .cm_header = { |
| /*add one for keeper.*/ |
| .buf_size = MMU_COMPRESS_HEADER_SIZE * |
| (FRAME_BUFFERS + 1), |
| /* 0x44000 = ((1088*2*1024*4)/32/4)*(32/8) */ |
| }, |
| #endif |
| #endif |
| .mpred_above = { |
| .buf_size = 0x1e00, /* 2 * size of hevc*/ |
| }, |
| #ifdef MV_USE_FIXED_BUF |
| .mpred_mv = {/* 1080p, 0x40000 per buffer */ |
| .buf_size = CO_MV_BUF_SIZE_1080P * FRAME_BUFFERS, |
| }, |
| #endif |
| .rpm = { |
| .buf_size = RPM_BUF_SIZE, |
| }, |
| .lmem = { |
| .buf_size = 0x400 * 2, |
| } |
| }, |
| { |
| .max_width = 4096, |
| .max_height = 2304, |
| .ipp = { |
| /* IPP work space calculation : |
| 4096 * (Y+CbCr+Flags) = 12k, round to 16k */ |
| .buf_size = 0x4000, |
| }, |
| .sao_abv = { |
| .buf_size = 0, |
| }, |
| .sao_vb = { |
| .buf_size = 0, |
| }, |
| .short_term_rps = { |
| /* SHORT_TERM_RPS - Max 64 set, 16 entry every set, |
| total 64x16x2 = 2048 bytes (0x800) */ |
| .buf_size = 0x800, |
| }, |
| .rcs = { |
| /* RCS STORE AREA - Max 16 RCS, each has 32 bytes, |
| total 0x0400 bytes */ |
| .buf_size = 0x400, |
| }, |
| .sps = { |
| /* SPS STORE AREA - Max 16 SPS, each has 0x80 bytes, |
| total 0x0800 bytes */ |
| .buf_size = 0x800, |
| }, |
| .pps = { |
| /* PPS STORE AREA - Max 64 PPS, each has 0x80 bytes, |
| total 0x2000 bytes */ |
| .buf_size = 0x2000, |
| }, |
| .sao_up = { |
| /* SAO UP STORE AREA - Max 640(10240/16) LCU, |
| each has 16 bytes total 0x2800 bytes */ |
| .buf_size = 0, |
| }, |
| .swap_buf = { |
| /* 256cyclex64bit = 2K bytes 0x800 |
| (only 144 cycles valid) */ |
| .buf_size = 0x800, |
| }, |
| .swap_buf2 = { |
| .buf_size = 0x800, |
| }, |
| .scalelut = { |
| /* support up to 32 SCALELUT 1024x32 = 32Kbytes |
| (0x8000) */ |
| .buf_size = 0, |
| }, |
| .dblk_para = { |
| /* DBLK -> Max 256(4096/16) LCU, |
| each para 1024bytes(total:0x40000), |
| data 1024bytes(total:0x40000)*/ |
| .buf_size = 0x8100, //0x8080, |
| }, |
| .dblk_data = { |
| /*DBLK -> Max 256(4096/16) LCU, |
| each para 1024bytes(total:0x40000), |
| data 1024bytes(total:0x40000)*/ |
| .buf_size = 0x88800, |
| }, |
| .dblk_data2 = { |
| .buf_size = 0x88800, |
| }, |
| #ifdef AVS2_10B_MMU |
| .mmu_vbh = { |
| .buf_size = VBH_BUF_SIZE_4K,/*2*16*(more than 2304)/4, 4K*/ |
| }, |
| #if 0 |
| .cm_header = { |
| /*add one for keeper.*/ |
| .buf_size = MMU_COMPRESS_HEADER_SIZE * |
| (FRAME_BUFFERS + 1), |
| /* 0x44000 = ((1088*2*1024*4)/32/4)*(32/8) */ |
| }, |
| #endif |
| #endif |
| .mpred_above = { |
| .buf_size = 0x4000, /* 2 * size of hevc*/ |
| }, |
| #ifdef MV_USE_FIXED_BUF |
| .mpred_mv = { |
| /* .buf_size = 0x100000*16, |
| //4k2k , 0x100000 per buffer */ |
| /* 4096x2304 , 0x120000 per buffer */ |
| .buf_size = CO_MV_BUF_SIZE_4K * FRAME_BUFFERS, |
| }, |
| #endif |
| .rpm = { |
| .buf_size = RPM_BUF_SIZE, |
| }, |
| .lmem = { |
| .buf_size = 0x400 * 2, |
| } |
| }, |
| { |
| .max_width = 4096 * 2, |
| .max_height = 2304 * 2, |
| .ipp = { |
| /*IPP work space calculation : 4096 * (Y+CbCr+Flags) = 12k, |
| round to 16k*/ |
| .buf_size = 0x4000 * 2, |
| }, |
| .sao_abv = { |
| .buf_size = 0, |
| }, |
| .sao_vb = { |
| .buf_size = 0, |
| }, |
| .short_term_rps = { |
| /*SHORT_TERM_RPS - Max 64 set, 16 entry every set, |
| total 64x16x2 = 2048 bytes (0x800)*/ |
| .buf_size = 0x800, |
| }, |
| .rcs = { |
| /*RCS STORE AREA - Max 16 RCS, each has 32 bytes, |
| total 0x0400 bytes*/ |
| .buf_size = 0x400, |
| }, |
| .sps = { |
| /*SPS STORE AREA - Max 16 SPS, each has 0x80 bytes, |
| total 0x0800 bytes*/ |
| .buf_size = 0x800, |
| }, |
| .pps = { |
| /*PPS STORE AREA - Max 64 PPS, each has 0x80 bytes, total |
| 0x2000 bytes*/ |
| .buf_size = 0x2000, |
| }, |
| .sao_up = { |
| /*SAO UP STORE AREA - Max 640(10240/16) LCU, each has 16 bytes i |
| total 0x2800 bytes*/ |
| .buf_size = 0, |
| }, |
| .swap_buf = { |
| /*256cyclex64bit = 2K bytes 0x800 (only 144 cycles valid)*/ |
| .buf_size = 0x800, |
| }, |
| .swap_buf2 = { |
| .buf_size = 0x800, |
| }, |
| .scalelut = { |
| /*support up to 32 SCALELUT 1024x32 = 32Kbytes (0x8000)*/ |
| .buf_size = 0, |
| }, |
| .dblk_para = { |
| .buf_size = 0x10100, //0x10080, |
| }, |
| .dblk_data = { |
| .buf_size = 0x110800, |
| }, |
| .dblk_data2 = { |
| .buf_size = 0x110800, |
| }, |
| #ifdef AVS2_10B_MMU |
| .mmu_vbh = { |
| .buf_size = VBH_BUF_SIZE_8K, /*2*16*2304/4, 4K*/ |
| }, |
| #if 0 |
| .cm_header = { |
| /*0x44000 = ((1088*2*1024*4)/32/4)*(32/8)*/ |
| .buf_size = MMU_COMPRESS_8K_HEADER_SIZE * 17, |
| }, |
| #endif |
| #endif |
| .mpred_above = { |
| .buf_size = 0x8000, |
| }, |
| #ifdef MV_USE_FIXED_BUF |
| .mpred_mv = { |
| /*4k2k , 0x100000 per buffer*/ |
| .buf_size = CO_MV_BUF_SIZE_8K * FRAME_BUFFERS, |
| }, |
| #endif |
| .rpm = { |
| .buf_size = RPM_BUF_SIZE, |
| }, |
| .lmem = { |
| .buf_size = 0x400 * 2, |
| } |
| } |
| }; |
| |
| #define IS_8K_SIZE(w, h) (((w) * (h)) > MAX_SIZE_4K) |
| #define IS_4K_SIZE(w, h) (((w) * (h)) > (1920*1088)) |
| #ifndef MV_USE_FIXED_BUF |
| static uint32_t get_mv_buf_size(struct AVS2Decoder_s *dec, int width, int height) { |
| struct avs2_decoder *avs2_dec = &dec->avs2_dec; |
| uint32_t size; |
| if (mv_buf_dynamic_alloc == 1) { |
| int mv_mem_unit = |
| avs2_dec->lcu_size_log2 == 6 ? 0x200 : avs2_dec->lcu_size_log2 == |
| 5 ? 0x80 : 0x20; |
| int extended_pic_width = (width + avs2_dec->lcu_size -1) |
| & (~(avs2_dec->lcu_size - 1)); |
| int extended_pic_height = (height + avs2_dec->lcu_size -1) |
| & (~(avs2_dec->lcu_size - 1)); |
| int lcu_x_num = extended_pic_width / avs2_dec->lcu_size; |
| int lcu_y_num = extended_pic_height / avs2_dec->lcu_size; |
| int new_size = lcu_x_num * lcu_y_num * mv_mem_unit; |
| size = (new_size + 0xffff) & (~0xffff); |
| |
| } else { |
| if (IS_8K_SIZE(width, height)) |
| size = CO_MV_BUF_SIZE_8K; |
| else if (IS_4K_SIZE(width, height)) |
| size = CO_MV_BUF_SIZE_4K; |
| else |
| size = CO_MV_BUF_SIZE_1080P; |
| } |
| return size; |
| } |
| #endif |
| |
| /*Losless compression body buffer size 4K per 64x32 (jt)*/ |
| static int compute_losless_comp_body_size(struct AVS2Decoder_s *dec, |
| int width, int height, |
| uint8_t is_bit_depth_10) |
| { |
| int width_x64; |
| int height_x32; |
| int bsize; |
| width_x64 = width + 63; |
| width_x64 >>= 6; |
| height_x32 = height + 31; |
| height_x32 >>= 5; |
| #ifdef AVS2_10B_MMU |
| bsize = (is_bit_depth_10 ? 4096 : 3200) |
| * width_x64 * height_x32; |
| #else |
| bsize = (is_bit_depth_10 ? 4096 : 3072) |
| * width_x64 * height_x32; |
| #endif |
| avs2_print(dec, AVS2_DBG_BUFMGR_MORE, |
| "%s(%d,%d,%d)=>%d\n", |
| __func__, width, height, |
| is_bit_depth_10, bsize); |
| |
| return bsize; |
| } |
| |
| /* Losless compression header buffer size 32bytes per 128x64 (jt)*/ |
| static int compute_losless_comp_header_size(struct AVS2Decoder_s *dec, |
| int width, int height) |
| { |
| int width_x128; |
| int height_x64; |
| int hsize; |
| width_x128 = width + 127; |
| width_x128 >>= 7; |
| height_x64 = height + 63; |
| height_x64 >>= 6; |
| |
| hsize = 32 * width_x128 * height_x64; |
| avs2_print(dec, AVS2_DBG_BUFMGR_MORE, |
| "%s(%d,%d)=>%d\n", |
| __func__, width, height, |
| hsize); |
| |
| return hsize; |
| } |
| |
| static void init_buff_spec(struct AVS2Decoder_s *dec, |
| struct BuffInfo_s *buf_spec) |
| { |
| void *mem_start_virt; |
| buf_spec->ipp.buf_start = buf_spec->start_adr; |
| buf_spec->sao_abv.buf_start = |
| buf_spec->ipp.buf_start + buf_spec->ipp.buf_size; |
| |
| buf_spec->sao_vb.buf_start = |
| buf_spec->sao_abv.buf_start + buf_spec->sao_abv.buf_size; |
| buf_spec->short_term_rps.buf_start = |
| buf_spec->sao_vb.buf_start + buf_spec->sao_vb.buf_size; |
| buf_spec->rcs.buf_start = |
| buf_spec->short_term_rps.buf_start + |
| buf_spec->short_term_rps.buf_size; |
| buf_spec->sps.buf_start = |
| buf_spec->rcs.buf_start + buf_spec->rcs.buf_size; |
| buf_spec->pps.buf_start = |
| buf_spec->sps.buf_start + buf_spec->sps.buf_size; |
| buf_spec->sao_up.buf_start = |
| buf_spec->pps.buf_start + buf_spec->pps.buf_size; |
| buf_spec->swap_buf.buf_start = |
| buf_spec->sao_up.buf_start + buf_spec->sao_up.buf_size; |
| buf_spec->swap_buf2.buf_start = |
| buf_spec->swap_buf.buf_start + buf_spec->swap_buf.buf_size; |
| buf_spec->scalelut.buf_start = |
| buf_spec->swap_buf2.buf_start + buf_spec->swap_buf2.buf_size; |
| buf_spec->dblk_para.buf_start = |
| buf_spec->scalelut.buf_start + buf_spec->scalelut.buf_size; |
| buf_spec->dblk_data.buf_start = |
| buf_spec->dblk_para.buf_start + buf_spec->dblk_para.buf_size; |
| buf_spec->dblk_data2.buf_start = |
| buf_spec->dblk_data.buf_start + buf_spec->dblk_data.buf_size; |
| #ifdef AVS2_10B_MMU |
| buf_spec->mmu_vbh.buf_start = |
| buf_spec->dblk_data2.buf_start + buf_spec->dblk_data2.buf_size; |
| buf_spec->mpred_above.buf_start = |
| buf_spec->mmu_vbh.buf_start + buf_spec->mmu_vbh.buf_size; |
| #else |
| buf_spec->mpred_above.buf_start = |
| buf_spec->dblk_data2.buf_start + buf_spec->dblk_data2.buf_size; |
| #endif |
| #ifdef MV_USE_FIXED_BUF |
| buf_spec->mpred_mv.buf_start = |
| buf_spec->mpred_above.buf_start + |
| buf_spec->mpred_above.buf_size; |
| |
| buf_spec->rpm.buf_start = |
| buf_spec->mpred_mv.buf_start + |
| buf_spec->mpred_mv.buf_size; |
| #else |
| buf_spec->rpm.buf_start = |
| buf_spec->mpred_above.buf_start + |
| buf_spec->mpred_above.buf_size; |
| |
| #endif |
| buf_spec->lmem.buf_start = |
| buf_spec->rpm.buf_start + |
| buf_spec->rpm.buf_size; |
| buf_spec->end_adr = |
| buf_spec->lmem.buf_start + |
| buf_spec->lmem.buf_size; |
| |
| if (dec) { |
| mem_start_virt = |
| codec_mm_phys_to_virt(buf_spec->dblk_para.buf_start); |
| if (mem_start_virt) { |
| memset(mem_start_virt, 0, buf_spec->dblk_para.buf_size); |
| codec_mm_dma_flush(mem_start_virt, |
| buf_spec->dblk_para.buf_size, |
| DMA_TO_DEVICE); |
| } else { |
| /*not virt for tvp playing, |
| may need clear on ucode.*/ |
| pr_err("mem_start_virt failed\n"); |
| } |
| if (debug) { |
| pr_info("%s workspace (%x %x) size = %x\n", __func__, |
| buf_spec->start_adr, buf_spec->end_adr, |
| buf_spec->end_adr - buf_spec->start_adr); |
| } |
| if (debug) { |
| pr_info("ipp.buf_start :%x\n", |
| buf_spec->ipp.buf_start); |
| pr_info("sao_abv.buf_start :%x\n", |
| buf_spec->sao_abv.buf_start); |
| pr_info("sao_vb.buf_start :%x\n", |
| buf_spec->sao_vb.buf_start); |
| pr_info("short_term_rps.buf_start :%x\n", |
| buf_spec->short_term_rps.buf_start); |
| pr_info("rcs.buf_start :%x\n", |
| buf_spec->rcs.buf_start); |
| pr_info("sps.buf_start :%x\n", |
| buf_spec->sps.buf_start); |
| pr_info("pps.buf_start :%x\n", |
| buf_spec->pps.buf_start); |
| pr_info("sao_up.buf_start :%x\n", |
| buf_spec->sao_up.buf_start); |
| pr_info("swap_buf.buf_start :%x\n", |
| buf_spec->swap_buf.buf_start); |
| pr_info("swap_buf2.buf_start :%x\n", |
| buf_spec->swap_buf2.buf_start); |
| pr_info("scalelut.buf_start :%x\n", |
| buf_spec->scalelut.buf_start); |
| pr_info("dblk_para.buf_start :%x\n", |
| buf_spec->dblk_para.buf_start); |
| pr_info("dblk_data.buf_start :%x\n", |
| buf_spec->dblk_data.buf_start); |
| pr_info("dblk_data2.buf_start :%x\n", |
| buf_spec->dblk_data2.buf_start); |
| #ifdef AVS2_10B_MMU |
| pr_info("mmu_vbh.buf_start :%x\n", |
| buf_spec->mmu_vbh.buf_start); |
| #endif |
| pr_info("mpred_above.buf_start :%x\n", |
| buf_spec->mpred_above.buf_start); |
| #ifdef MV_USE_FIXED_BUF |
| pr_info("mpred_mv.buf_start :%x\n", |
| buf_spec->mpred_mv.buf_start); |
| #endif |
| if ((debug & AVS2_DBG_SEND_PARAM_WITH_REG) == 0) { |
| pr_info("rpm.buf_start :%x\n", |
| buf_spec->rpm.buf_start); |
| } |
| } |
| } |
| |
| } |
| |
| static void uninit_mmu_buffers(struct AVS2Decoder_s *dec) |
| { |
| #if 0 |
| /*ndef MV_USE_FIXED_BUF*/ |
| dealloc_mv_bufs(dec); |
| #endif |
| decoder_mmu_box_free(dec->mmu_box); |
| dec->mmu_box = NULL; |
| |
| if (dec->bmmu_box) |
| decoder_bmmu_box_free(dec->bmmu_box); |
| dec->bmmu_box = NULL; |
| } |
| |
| #ifndef AVS2_10B_MMU |
| static void init_buf_list(struct AVS2Decoder_s *dec) |
| { |
| int i; |
| int buf_size; |
| int mc_buffer_end = dec->mc_buf->buf_start + dec->mc_buf->buf_size; |
| dec->used_buf_num = max_buf_num; |
| |
| if (dec->used_buf_num > MAX_BUF_NUM) |
| dec->used_buf_num = MAX_BUF_NUM; |
| if (buf_alloc_size > 0) { |
| buf_size = buf_alloc_size; |
| avs2_print(dec, AVS2_DBG_BUFMGR, |
| "[Buffer Management] init_buf_list:\n"); |
| } else { |
| int pic_width = dec->init_pic_w; |
| int pic_height = dec->init_pic_h; |
| |
| /*SUPPORT_10BIT*/ |
| int losless_comp_header_size = compute_losless_comp_header_size |
| (dec, pic_width, pic_height); |
| int losless_comp_body_size = compute_losless_comp_body_size |
| (dec, pic_width, pic_height, buf_alloc_depth == 10); |
| int mc_buffer_size = losless_comp_header_size |
| + losless_comp_body_size; |
| int mc_buffer_size_h = (mc_buffer_size + 0xffff)>>16; |
| |
| int dw_mode = get_double_write_mode_init(dec); |
| |
| if (dw_mode) { |
| int pic_width_dw = pic_width / |
| get_double_write_ratio(dec, dw_mode); |
| int pic_height_dw = pic_height / |
| get_double_write_ratio(dec, dw_mode); |
| int lcu_size = 64; /*fixed 64*/ |
| int pic_width_64 = (pic_width_dw + 63) & (~0x3f); |
| int pic_height_32 = (pic_height_dw + 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 mc_buffer_size_u_v = lcu_total * lcu_size * lcu_size / 2; |
| int mc_buffer_size_u_v_h = (mc_buffer_size_u_v + 0xffff) >> 16; |
| /*64k alignment*/ |
| buf_size = ((mc_buffer_size_u_v_h << 16) * 3); |
| } else |
| buf_size = 0; |
| |
| if (mc_buffer_size & 0xffff) { /*64k alignment*/ |
| mc_buffer_size_h += 1; |
| } |
| if ((dw_mode & 0x10) == 0) |
| buf_size += (mc_buffer_size_h << 16); |
| avs2_print(dec, AVS2_DBG_BUFMGR, |
| "init_buf_list num %d (width %d height %d):\n", |
| dec->used_buf_num, pic_width, pic_height); |
| } |
| |
| for (i = 0; i < dec->used_buf_num; i++) { |
| if (((i + 1) * buf_size) > dec->mc_buf->buf_size) |
| dec->use_cma_flag = 1; |
| #ifndef AVS2_10B_MMU |
| dec->m_BUF[i].alloc_flag = 0; |
| dec->m_BUF[i].index = i; |
| |
| dec->use_cma_flag = 1; |
| if (dec->use_cma_flag) { |
| dec->m_BUF[i].cma_page_count = |
| PAGE_ALIGN(buf_size) / PAGE_SIZE; |
| if (decoder_bmmu_box_alloc_buf_phy(dec->bmmu_box, |
| VF_BUFFER_IDX(i), buf_size, DRIVER_NAME, |
| &dec->m_BUF[i].alloc_addr) < 0) { |
| dec->m_BUF[i].cma_page_count = 0; |
| if (i <= 5) { |
| dec->fatal_error |= |
| DECODER_FATAL_ERROR_NO_MEM; |
| } |
| break; |
| } |
| dec->m_BUF[i].start_adr = dec->m_BUF[i].alloc_addr; |
| } else { |
| dec->m_BUF[i].cma_page_count = 0; |
| dec->m_BUF[i].alloc_addr = 0; |
| dec->m_BUF[i].start_adr = |
| dec->mc_buf->buf_start + i * buf_size; |
| } |
| dec->m_BUF[i].size = buf_size; |
| dec->m_BUF[i].free_start_adr = dec->m_BUF[i].start_adr; |
| |
| if (((dec->m_BUF[i].start_adr + buf_size) > mc_buffer_end) |
| && (dec->m_BUF[i].alloc_addr == 0)) { |
| if (debug) { |
| avs2_print(dec, 0, |
| "Max mc buffer or mpred_mv buffer is used\n"); |
| } |
| break; |
| } |
| |
| avs2_print(dec, AVS2_DBG_BUFMGR, |
| "Buffer %d: start_adr %p size %x\n", i, |
| (void *)dec->m_BUF[i].start_adr, |
| dec->m_BUF[i].size); |
| #endif |
| } |
| dec->buf_num = i; |
| } |
| #endif |
| |
| static int config_pic(struct AVS2Decoder_s *dec, |
| struct avs2_frame_s *pic, int32_t lcu_size_log2) |
| { |
| int ret = -1; |
| int i; |
| int pic_width = dec->init_pic_w; |
| int pic_height = dec->init_pic_h; |
| /*struct avs2_decoder *avs2_dec = &dec->avs2_dec; |
| int32_t lcu_size_log2 = avs2_dec->lcu_size_log2;*/ |
| int32_t lcu_size = 1 << lcu_size_log2; |
| 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; |
| #if 0 |
| int32_t MV_MEM_UNIT = |
| (lcu_size_log2 == 6) ? 0x200 : |
| ((lcu_size_log2 == 5) ? 0x80 : 0x20); |
| #endif |
| #ifdef MV_USE_FIXED_BUF |
| u32 mpred_mv_end = dec->work_space_buf->mpred_mv.buf_start + |
| dec->work_space_buf->mpred_mv.buf_size; |
| #endif |
| u32 y_adr = 0; |
| int buf_size = 0; |
| |
| int losless_comp_header_size = |
| compute_losless_comp_header_size( |
| dec, pic_width, pic_height); |
| int losless_comp_body_size = compute_losless_comp_body_size( |
| dec, pic_width, |
| pic_height, buf_alloc_depth == 10); |
| int mc_buffer_size = losless_comp_header_size + losless_comp_body_size; |
| int mc_buffer_size_h = (mc_buffer_size + 0xffff) >> 16; |
| int mc_buffer_size_u_v = 0; |
| int mc_buffer_size_u_v_h = 0; |
| int dw_mode = get_double_write_mode_init(dec); |
| |
| if (dw_mode) { |
| int pic_width_dw = pic_width / |
| get_double_write_ratio(dec, dw_mode); |
| int pic_height_dw = pic_height / |
| get_double_write_ratio(dec, dw_mode); |
| int pic_width_64_dw = (pic_width_dw + 63) & (~0x3f); |
| int pic_height_32_dw = (pic_height_dw + 31) & (~0x1f); |
| int pic_width_lcu_dw = (pic_width_64_dw % lcu_size) ? |
| pic_width_64_dw / lcu_size + 1 |
| : pic_width_64_dw / lcu_size; |
| int pic_height_lcu_dw = (pic_height_32_dw % lcu_size) ? |
| pic_height_32_dw / lcu_size + 1 |
| : pic_height_32_dw / lcu_size; |
| int lcu_total_dw = pic_width_lcu_dw * pic_height_lcu_dw; |
| |
| mc_buffer_size_u_v = lcu_total_dw * lcu_size * lcu_size / 2; |
| mc_buffer_size_u_v_h = (mc_buffer_size_u_v + 0xffff) >> 16; |
| /*64k alignment*/ |
| buf_size = ((mc_buffer_size_u_v_h << 16) * 3); |
| buf_size = ((buf_size + 0xffff) >> 16) << 16; |
| } |
| if (mc_buffer_size & 0xffff) /*64k alignment*/ |
| mc_buffer_size_h += 1; |
| #ifndef AVS2_10B_MMU |
| if ((dw_mode & 0x10) == 0) |
| buf_size += (mc_buffer_size_h << 16); |
| #endif |
| |
| #ifdef AVS2_10B_MMU |
| #ifndef DYNAMIC_ALLOC_HEAD |
| pic->header_adr = decoder_bmmu_box_get_phy_addr( |
| dec->bmmu_box, HEADER_BUFFER_IDX(pic->index)); |
| |
| avs2_print(dec, AVS2_DBG_BUFMGR_MORE, |
| "buf_size %d, MMU header_adr %d: %ld\n", |
| buf_size, pic->index, pic->header_adr); |
| #endif |
| #endif |
| |
| i = pic->index; |
| #ifdef MV_USE_FIXED_BUF |
| #ifdef G12A_BRINGUP_DEBUG |
| if (1) { |
| #else |
| if ((dec->work_space_buf->mpred_mv.buf_start + |
| (((i + 1) * lcu_total) * MV_MEM_UNIT)) |
| <= mpred_mv_end |
| ) { |
| #endif |
| #endif |
| #ifndef AVS2_10B_MMU |
| if (debug) { |
| pr_err("start %x .size=%d\n", |
| dec->mc_buf_spec.buf_start + i * buf_size, |
| buf_size); |
| } |
| #endif |
| #ifndef AVS2_10B_MMU |
| for (i = 0; i < dec->buf_num; i++) { |
| y_adr = ((dec->m_BUF[i].free_start_adr |
| + 0xffff) >> 16) << 16; |
| /*64k alignment*/ |
| if ((y_adr+buf_size) <= (dec->m_BUF[i].start_adr+ |
| dec->m_BUF[i].size)) { |
| dec->m_BUF[i].free_start_adr = |
| y_adr + buf_size; |
| break; |
| } |
| } |
| if (i < dec->buf_num) |
| #else |
| /*if ((dec->mc_buf->buf_start + (i + 1) * buf_size) < |
| dec->mc_buf->buf_end) |
| y_adr = dec->mc_buf->buf_start + i * buf_size; |
| else {*/ |
| if (buf_size > 0 && pic->cma_alloc_addr == 0) { |
| ret = decoder_bmmu_box_alloc_buf_phy(dec->bmmu_box, |
| VF_BUFFER_IDX(i), |
| buf_size, DRIVER_NAME, |
| &pic->cma_alloc_addr); |
| if (ret < 0) { |
| avs2_print(dec, 0, |
| "decoder_bmmu_box_alloc_buf_phy idx %d size %d fail\n", |
| VF_BUFFER_IDX(i), |
| buf_size |
| ); |
| return ret; |
| } |
| |
| if (pic->cma_alloc_addr) |
| y_adr = pic->cma_alloc_addr; |
| else { |
| avs2_print(dec, 0, |
| "decoder_bmmu_box_alloc_buf_phy idx %d size %d return null\n", |
| VF_BUFFER_IDX(i), |
| buf_size |
| ); |
| return -1; |
| } |
| } |
| #endif |
| { |
| /*ensure get_pic_by_POC() |
| not get the buffer not decoded*/ |
| pic->BUF_index = i; |
| pic->lcu_total = lcu_total; |
| |
| pic->comp_body_size = losless_comp_body_size; |
| pic->buf_size = buf_size; |
| #ifndef AVS2_10B_MMU |
| pic->mc_y_adr = y_adr; |
| #endif |
| pic->mc_canvas_y = pic->index; |
| pic->mc_canvas_u_v = pic->index; |
| #ifndef AVS2_10B_MMU |
| if (dw_mode & 0x10) { |
| pic->mc_u_v_adr = y_adr + |
| ((mc_buffer_size_u_v_h << 16) << 1); |
| |
| pic->mc_canvas_y = |
| (pic->index << 1); |
| pic->mc_canvas_u_v = |
| (pic->index << 1) + 1; |
| |
| pic->dw_y_adr = y_adr; |
| pic->dw_u_v_adr = pic->mc_u_v_adr; |
| } else |
| #endif |
| if (dw_mode) { |
| pic->dw_y_adr = y_adr |
| #ifndef AVS2_10B_MMU |
| + (mc_buffer_size_h << 16) |
| #endif |
| ; |
| pic->dw_u_v_adr = pic->dw_y_adr + |
| ((mc_buffer_size_u_v_h << 16) << 1); |
| #ifdef AVS2_10B_MMU |
| pic->mc_y_adr = pic->dw_y_adr; |
| pic->mc_u_v_adr = pic->dw_u_v_adr; |
| #endif |
| } |
| #ifdef MV_USE_FIXED_BUF |
| #ifdef G12A_BRINGUP_DEBUG |
| if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { |
| pic->mpred_mv_wr_start_addr = |
| dec->work_space_buf->mpred_mv.buf_start + |
| (pic->index * 0x120000 * 4); |
| } else { |
| pic->mpred_mv_wr_start_addr = |
| dec->work_space_buf->mpred_mv.buf_start + |
| (pic->index * 0x120000); |
| } |
| #else |
| pic->mpred_mv_wr_start_addr = |
| dec->work_space_buf->mpred_mv.buf_start + |
| ((pic->index * lcu_total) |
| * MV_MEM_UNIT); |
| #endif |
| #endif |
| if (debug) { |
| avs2_print(dec, AVS2_DBG_BUFMGR, |
| "%s index %d BUF_index %d mc_y_adr %x ", |
| __func__, pic->index, |
| pic->BUF_index, |
| pic->mc_y_adr); |
| avs2_print_cont(dec, AVS2_DBG_BUFMGR, |
| "comp_body_size %x comp_buf_size %x ", |
| pic->comp_body_size, |
| pic->buf_size); |
| avs2_print_cont(dec, AVS2_DBG_BUFMGR, |
| "mpred_mv_wr_start_adr %d\n", |
| pic->mpred_mv_wr_start_addr); |
| avs2_print_cont(dec, AVS2_DBG_BUFMGR, |
| "dw_y_adr %d, pic->dw_u_v_adr =%d\n", |
| pic->dw_y_adr, |
| pic->dw_u_v_adr); |
| } |
| ret = 0; |
| } |
| #ifdef MV_USE_FIXED_BUF |
| } else { |
| avs2_print(dec, 0, |
| "mv buffer alloc fail %x > %x\n", |
| dec->work_space_buf->mpred_mv.buf_start + |
| (((i + 1) * lcu_total) * MV_MEM_UNIT), |
| mpred_mv_end); |
| } |
| #endif |
| return ret; |
| } |
| |
| static void init_pic_list(struct AVS2Decoder_s *dec, |
| int32_t lcu_size_log2) |
| { |
| int i; |
| struct avs2_decoder *avs2_dec = &dec->avs2_dec; |
| struct avs2_frame_s *pic; |
| #ifdef AVS2_10B_MMU |
| unsigned long buf_addr1; |
| /*alloc AVS2 compress header first*/ |
| if (decoder_bmmu_box_alloc_buf_phy |
| (dec->bmmu_box, |
| HEADER_BUFFER_IDX(-1), get_compress_header_size(dec), |
| DRIVER_HEADER_NAME, |
| &buf_addr1) < 0){ |
| avs2_print(dec, 0, |
| "%s malloc compress header failed %d\n", |
| DRIVER_HEADER_NAME, -1); |
| dec->fatal_error |= DECODER_FATAL_ERROR_NO_MEM; |
| return; |
| } |
| #ifndef DYNAMIC_ALLOC_HEAD |
| for (i = 0; i < dec->used_buf_num; i++) { |
| unsigned long buf_addr; |
| if (decoder_bmmu_box_alloc_buf_phy |
| (dec->bmmu_box, |
| HEADER_BUFFER_IDX(i), get_compress_header_size(dec), |
| DRIVER_HEADER_NAME, |
| &buf_addr) < 0){ |
| avs2_print(dec, 0, |
| "%s malloc compress header failed %d\n", |
| DRIVER_HEADER_NAME, i); |
| dec->fatal_error |= DECODER_FATAL_ERROR_NO_MEM; |
| return; |
| } |
| } |
| #endif |
| #endif |
| dec->frame_height = avs2_dec->img.height; |
| dec->frame_width = avs2_dec->img.width; |
| |
| for (i = 0; i < dec->used_buf_num; i++) { |
| if (i == (dec->used_buf_num - 1)) |
| pic = avs2_dec->m_bg; |
| else |
| pic = avs2_dec->fref[i]; |
| pic->index = i; |
| pic->BUF_index = -1; |
| pic->mv_buf_index = -1; |
| if (config_pic(dec, pic, lcu_size_log2) < 0) { |
| if (debug) |
| avs2_print(dec, 0, |
| "Config_pic %d fail\n", |
| pic->index); |
| pic->index = -1; |
| break; |
| } |
| pic->pic_w = avs2_dec->img.width; |
| pic->pic_h = avs2_dec->img.height; |
| } |
| for (; i < dec->used_buf_num; i++) { |
| if (i == (dec->used_buf_num - 1)) |
| pic = avs2_dec->m_bg; |
| else |
| pic = avs2_dec->fref[i]; |
| pic->index = -1; |
| pic->BUF_index = -1; |
| pic->mv_buf_index = -1; |
| } |
| avs2_print(dec, AVS2_DBG_BUFMGR, |
| "%s ok, used_buf_num = %d\n", |
| __func__, dec->used_buf_num); |
| dec->pic_list_init_flag = 1; |
| } |
| |
| |
| static void init_pic_list_hw(struct AVS2Decoder_s *dec) |
| { |
| int i; |
| struct avs2_decoder *avs2_dec = &dec->avs2_dec; |
| struct avs2_frame_s *pic; |
| /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 0x0);*/ |
| #if 0 |
| WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, |
| (0x1 << 1) | (0x1 << 2)); |
| |
| #ifdef DUAL_CORE_64 |
| WRITE_VREG(HEVC2_HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, |
| (0x1 << 1) | (0x1 << 2)); |
| #endif |
| #endif |
| for (i = 0; i < dec->used_buf_num; i++) { |
| if (i == (dec->used_buf_num - 1)) |
| pic = avs2_dec->m_bg; |
| else |
| pic = avs2_dec->fref[i]; |
| if (pic->index < 0) |
| break; |
| #ifdef AVS2_10B_MMU |
| /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR, |
| pic->header_adr |
| | (pic->mc_canvas_y << 8)|0x1);*/ |
| WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, |
| (0x1 << 1) | (pic->index << 8)); |
| |
| #ifdef DUAL_CORE_64 |
| if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXLX2) |
| WRITE_VREG(HEVC2_MPP_ANC2AXI_TBL_CONF_ADDR, |
| (0x1 << 1) | (pic->index << 8)); |
| else |
| WRITE_VREG(HEVC2_HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, |
| (0x1 << 1) | (pic->index << 8)); |
| #endif |
| WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, pic->header_adr >> 5); |
| #else |
| /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR, |
| pic->mc_y_adr |
| | (pic->mc_canvas_y << 8) | 0x1);*/ |
| WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, pic->mc_y_adr >> 5); |
| #endif |
| #ifndef LOSLESS_COMPRESS_MODE |
| /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR, |
| pic->mc_u_v_adr |
| | (pic->mc_canvas_u_v << 8)| 0x1);*/ |
| WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, pic->mc_u_v_adr >> 5); |
| #endif |
| #ifdef DUAL_CORE_64 |
| #ifdef AVS2_10B_MMU |
| WRITE_VREG(HEVC2_HEVCD_MPP_ANC2AXI_TBL_DATA, |
| pic->header_adr >> 5); |
| #else |
| WRITE_VREG(HEVC2_HEVCD_MPP_ANC2AXI_TBL_DATA, |
| pic->mc_y_adr >> 5); |
| #endif |
| #ifndef LOSLESS_COMPRESS_MODE |
| WRITE_VREG(HEVC2_HEVCD_MPP_ANC2AXI_TBL_DATA, |
| pic->mc_u_v_adr >> 5); |
| #endif |
| /*DUAL_CORE_64*/ |
| #endif |
| } |
| WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 0x1); |
| #ifdef DUAL_CORE_64 |
| WRITE_VREG(HEVC2_HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, |
| 0x1); |
| #endif |
| /*Zero out canvas registers in IPP -- avoid simulation X*/ |
| WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, |
| (0 << 8) | (0 << 1) | 1); |
| for (i = 0; i < 32; i++) { |
| WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, 0); |
| #ifdef DUAL_CORE_64 |
| WRITE_VREG(HEVC2_HEVCD_MPP_ANC_CANVAS_DATA_ADDR, 0); |
| #endif |
| } |
| } |
| |
| |
| static void dump_pic_list(struct AVS2Decoder_s *dec) |
| { |
| int ii; |
| struct avs2_decoder *avs2_dec = &dec->avs2_dec; |
| for (ii = 0; ii < avs2_dec->ref_maxbuffer; ii++) { |
| avs2_print(dec, 0, |
| "fref[%d]: index %d decode_id %d mvbuf %d imgcoi_ref %d imgtr_fwRefDistance %d refered %d, pre %d is_out %d, bg %d, vf_ref %d error %d lcu %d ref_pos(%d,%d,%d,%d,%d,%d,%d)\n", |
| ii, avs2_dec->fref[ii]->index, |
| avs2_dec->fref[ii]->decode_idx, |
| avs2_dec->fref[ii]->mv_buf_index, |
| avs2_dec->fref[ii]->imgcoi_ref, |
| avs2_dec->fref[ii]->imgtr_fwRefDistance, |
| avs2_dec->fref[ii]->refered_by_others, |
| avs2_dec->fref[ii]->to_prepare_disp, |
| avs2_dec->fref[ii]->is_output, |
| avs2_dec->fref[ii]->bg_flag, |
| avs2_dec->fref[ii]->vf_ref, |
| avs2_dec->fref[ii]->error_mark, |
| avs2_dec->fref[ii]->decoded_lcu, |
| avs2_dec->fref[ii]->ref_poc[0], |
| avs2_dec->fref[ii]->ref_poc[1], |
| avs2_dec->fref[ii]->ref_poc[2], |
| avs2_dec->fref[ii]->ref_poc[3], |
| avs2_dec->fref[ii]->ref_poc[4], |
| avs2_dec->fref[ii]->ref_poc[5], |
| avs2_dec->fref[ii]->ref_poc[6] |
| ); |
| } |
| return; |
| } |
| |
| static int config_mc_buffer(struct AVS2Decoder_s *dec) |
| { |
| int32_t i; |
| struct avs2_decoder *avs2_dec = &dec->avs2_dec; |
| struct avs2_frame_s *pic; |
| struct avs2_frame_s *cur_pic = avs2_dec->hc.cur_pic; |
| |
| /*if (avs2_dec->img.type == I_IMG) |
| return 0; |
| */ |
| avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, |
| "Entered config_mc_buffer....\n"); |
| if (avs2_dec->f_bg != NULL) { |
| avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, |
| "config_mc_buffer for background (canvas_y %d, canvas_u_v %d)\n", |
| avs2_dec->f_bg->mc_canvas_y, avs2_dec->f_bg->mc_canvas_u_v); |
| /*WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, |
| (7 << 8) | (0<<1) | 1); L0:BG */ |
| WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, |
| (15 << 8) | (0<<1) | 1); /* L0:BG*/ |
| WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, |
| (avs2_dec->f_bg->mc_canvas_u_v << 16) | |
| (avs2_dec->f_bg->mc_canvas_u_v << 8) | |
| avs2_dec->f_bg->mc_canvas_y); |
| /*WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, |
| (23 << 8) | (0<<1) | 1); L1:BG*/ |
| WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, |
| (31 << 8) | (0<<1) | 1); /* L1:BG*/ |
| WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, |
| (avs2_dec->f_bg->mc_canvas_u_v << 16) | |
| (avs2_dec->f_bg->mc_canvas_u_v << 8) | |
| avs2_dec->f_bg->mc_canvas_y); |
| } |
| |
| if (avs2_dec->img.type == I_IMG) |
| return 0; |
| |
| if (avs2_dec->img.type == P_IMG) { |
| avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, |
| "config_mc_buffer for P_IMG, img type %d\n", |
| avs2_dec->img.type); |
| /*refer to prepare_RefInfo()*/ |
| WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, |
| (0 << 8) | (0<<1) | 1); |
| for (i = 0; i < avs2_dec->img.num_of_references; i++) { |
| pic = avs2_dec->fref[i]; |
| WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, |
| (pic->mc_canvas_u_v << 16) | |
| (pic->mc_canvas_u_v << 8) | |
| pic->mc_canvas_y); |
| |
| if (pic->error_mark) |
| cur_pic->error_mark = 1; |
| |
| avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, |
| "refid %x mc_canvas_u_v %x mc_canvas_y %x error_mark %x\n", |
| i, pic->mc_canvas_u_v, pic->mc_canvas_y, |
| pic->error_mark); |
| } |
| } else if (avs2_dec->img.type == F_IMG) { |
| avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, |
| "config_mc_buffer for F_IMG, img type %d\n", |
| avs2_dec->img.type); |
| /*refer to prepare_RefInfo()*/ |
| WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, |
| (0 << 8) | (0<<1) | 1); |
| for (i = 0; i < avs2_dec->img.num_of_references; i++) { |
| pic = avs2_dec->fref[i]; |
| WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, |
| (pic->mc_canvas_u_v << 16) | |
| (pic->mc_canvas_u_v << 8) | |
| pic->mc_canvas_y); |
| |
| if (pic->error_mark) |
| cur_pic->error_mark = 1; |
| |
| avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, |
| "refid %x mc_canvas_u_v %x mc_canvas_y %x error_mark %x\n", |
| i, pic->mc_canvas_u_v, pic->mc_canvas_y, |
| pic->error_mark); |
| } |
| WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, |
| (16 << 8) | (0<<1) | 1); |
| for (i = 0; i < avs2_dec->img.num_of_references; i++) { |
| pic = avs2_dec->fref[i]; |
| WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, |
| (pic->mc_canvas_u_v << 16) | |
| (pic->mc_canvas_u_v << 8) | |
| pic->mc_canvas_y); |
| avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, |
| "refid %x mc_canvas_u_v %x mc_canvas_y %x\n", |
| i, pic->mc_canvas_u_v, pic->mc_canvas_y); |
| } |
| } else { |
| avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, |
| "config_mc_buffer for B_IMG\n"); |
| /*refer to prepare_RefInfo()*/ |
| pic = avs2_dec->fref[1]; |
| WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, |
| (0 << 8) | (0<<1) | 1); |
| WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, |
| (pic->mc_canvas_u_v << 16) | |
| (pic->mc_canvas_u_v << 8) | |
| pic->mc_canvas_y); |
| |
| if (pic->error_mark) |
| cur_pic->error_mark = 1; |
| |
| avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, |
| "refid %x mc_canvas_u_v %x mc_canvas_y %x error_mark %x\n", |
| 1, pic->mc_canvas_u_v, pic->mc_canvas_y, |
| pic->error_mark); |
| |
| pic = avs2_dec->fref[0]; |
| WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, |
| (16 << 8) | (0<<1) | 1); |
| WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, |
| (pic->mc_canvas_u_v<<16) | |
| (pic->mc_canvas_u_v<<8) | |
| pic->mc_canvas_y); |
| |
| if (pic->error_mark) |
| cur_pic->error_mark = 1; |
| |
| avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, |
| "refid %x mc_canvas_u_v %x mc_canvas_y %x error_mark %x\n", |
| 0, pic->mc_canvas_u_v, pic->mc_canvas_y, |
| pic->error_mark); |
| } |
| return 0; |
| } |
| #if 0 |
| static void mcrcc_get_hitrate(void) |
| { |
| u32 tmp; |
| u32 raw_mcr_cnt; |
| u32 hit_mcr_cnt; |
| u32 byp_mcr_cnt_nchoutwin; |
| u32 byp_mcr_cnt_nchcanv; |
| int hitrate; |
| |
| if (debug & AVS2_DBG_CACHE) |
| pr_info("[cache_util.c] Entered mcrcc_get_hitrate...\n"); |
| WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x0<<1)); |
| raw_mcr_cnt = READ_VREG(HEVCD_MCRCC_PERFMON_DATA); |
| WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x1<<1)); |
| hit_mcr_cnt = READ_VREG(HEVCD_MCRCC_PERFMON_DATA); |
| WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x2<<1)); |
| byp_mcr_cnt_nchoutwin = READ_VREG(HEVCD_MCRCC_PERFMON_DATA); |
| WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x3<<1)); |
| byp_mcr_cnt_nchcanv = READ_VREG(HEVCD_MCRCC_PERFMON_DATA); |
| |
| if (debug & AVS2_DBG_CACHE) { |
| pr_info("raw_mcr_cnt_total: %d\n",raw_mcr_cnt); |
| pr_info("hit_mcr_cnt_total: %d\n",hit_mcr_cnt); |
| pr_info("byp_mcr_cnt_nchoutwin_total: %d\n",byp_mcr_cnt_nchoutwin); |
| pr_info("byp_mcr_cnt_nchcanv_total: %d\n",byp_mcr_cnt_nchcanv); |
| } |
| WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x4<<1)); |
| tmp = READ_VREG(HEVCD_MCRCC_PERFMON_DATA); |
| if (debug & AVS2_DBG_CACHE) |
| pr_info("miss_mcr_0_cnt_total: %d\n", tmp); |
| |
| WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x5<<1)); |
| tmp = READ_VREG(HEVCD_MCRCC_PERFMON_DATA); |
| if (debug & AVS2_DBG_CACHE) |
| pr_info("miss_mcr_1_cnt_total: %d\n", tmp); |
| |
| WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x6<<1)); |
| tmp = READ_VREG(HEVCD_MCRCC_PERFMON_DATA); |
| if (debug & AVS2_DBG_CACHE) |
| pr_info("hit_mcr_0_cnt_total: %d\n",tmp); |
| |
| WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x7<<1)); |
| tmp= READ_VREG(HEVCD_MCRCC_PERFMON_DATA); |
| if (debug & AVS2_DBG_CACHE) |
| pr_info("hit_mcr_1_cnt_total: %d\n",tmp); |
| |
| if (raw_mcr_cnt != 0) { |
| hitrate = (hit_mcr_cnt / raw_mcr_cnt) * 100; |
| if (debug & AVS2_DBG_CACHE) |
| pr_info("MCRCC_HIT_RATE : %d\n", hitrate); |
| hitrate = ((byp_mcr_cnt_nchoutwin + byp_mcr_cnt_nchcanv) |
| /raw_mcr_cnt) * 100; |
| if (debug & AVS2_DBG_CACHE) |
| pr_info("MCRCC_BYP_RATE : %d\n", hitrate); |
| } else if (debug & AVS2_DBG_CACHE) { |
| pr_info("MCRCC_HIT_RATE : na\n"); |
| pr_info("MCRCC_BYP_RATE : na\n"); |
| } |
| return; |
| } |
| |
| |
| static void decomp_get_hitrate(void) |
| { |
| u32 raw_mcr_cnt; |
| u32 hit_mcr_cnt; |
| int hitrate; |
| |
| if (debug & AVS2_DBG_CACHE) |
| pr_info("[cache_util.c] Entered decomp_get_hitrate...\n"); |
| WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x0<<1)); |
| raw_mcr_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA); |
| WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x1<<1)); |
| hit_mcr_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA); |
| |
| if (debug & AVS2_DBG_CACHE) { |
| pr_info("hcache_raw_cnt_total: %d\n",raw_mcr_cnt); |
| pr_info("hcache_hit_cnt_total: %d\n",hit_mcr_cnt); |
| } |
| if (raw_mcr_cnt != 0) { |
| hitrate = (hit_mcr_cnt / raw_mcr_cnt) * 100; |
| if (debug & AVS2_DBG_CACHE) |
| pr_info("DECOMP_HCACHE_HIT_RATE : %d\n", hitrate); |
| } else { |
| if (debug & AVS2_DBG_CACHE) |
| pr_info("DECOMP_HCACHE_HIT_RATE : na\n"); |
| } |
| WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x2<<1)); |
| raw_mcr_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA); |
| WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x3<<1)); |
| hit_mcr_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA); |
| |
| if (debug & AVS2_DBG_CACHE) { |
| pr_info("dcache_raw_cnt_total: %d\n", raw_mcr_cnt); |
| pr_info("dcache_hit_cnt_total: %d\n", hit_mcr_cnt); |
| } |
| if (raw_mcr_cnt != 0) { |
| hitrate = (hit_mcr_cnt / raw_mcr_cnt) * 100; |
| if (debug & AVS2_DBG_CACHE) |
| pr_info("DECOMP_DCACHE_HIT_RATE : %d\n", hitrate); |
| } else if (debug & AVS2_DBG_CACHE) { |
| pr_info("DECOMP_DCACHE_HIT_RATE : na\n"); |
| } |
| return; |
| } |
| |
| static void decomp_get_comprate(void) |
| { |
| u32 raw_ucomp_cnt; |
| u32 fast_comp_cnt; |
| u32 slow_comp_cnt; |
| int comprate; |
| |
| if (debug & AVS2_DBG_CACHE) |
| pr_info("[cache_util.c] Entered decomp_get_comprate...\n"); |
| WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x4<<1)); |
| fast_comp_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA); |
| WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x5<<1)); |
| slow_comp_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA); |
| WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x6<<1)); |
| raw_ucomp_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA); |
| if (debug & AVS2_DBG_CACHE) { |
| pr_info("decomp_fast_comp_total: %d\n", fast_comp_cnt); |
| pr_info("decomp_slow_comp_total: %d\n", slow_comp_cnt); |
| pr_info("decomp_raw_uncomp_total: %d\n", raw_ucomp_cnt); |
| } |
| |
| if (raw_ucomp_cnt != 0) { |
| comprate = ((fast_comp_cnt + slow_comp_cnt) |
| / raw_ucomp_cnt) * 100; |
| if (debug & AVS2_DBG_CACHE) |
| pr_info("DECOMP_COMP_RATIO : %d\n", comprate); |
| } else if (debug & AVS2_DBG_CACHE) { |
| pr_info("DECOMP_COMP_RATIO : na\n"); |
| } |
| return; |
| } |
| #endif |
| |
| static void config_mcrcc_axi_hw(struct AVS2Decoder_s *dec) |
| { |
| uint32_t rdata32; |
| uint32_t rdata32_2; |
| struct avs2_decoder *avs2_dec = &dec->avs2_dec; |
| |
| WRITE_VREG(HEVCD_MCRCC_CTL1, 0x2); /* reset mcrcc*/ |
| |
| if (avs2_dec->img.type == I_IMG) { /* I-PIC*/ |
| /* remove reset -- disables clock */ |
| WRITE_VREG(HEVCD_MCRCC_CTL1, 0x0); |
| return; |
| } |
| /* |
| if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { |
| mcrcc_get_hitrate(); |
| decomp_get_hitrate(); |
| decomp_get_comprate(); |
| } |
| */ |
| if ((avs2_dec->img.type == B_IMG) || |
| (avs2_dec->img.type == F_IMG)) { /*B-PIC or F_PIC*/ |
| /*Programme canvas0 */ |
| WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, |
| (0 << 8) | (0 << 1) | 0); |
| rdata32 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); |
| rdata32 = rdata32 & 0xffff; |
| rdata32 = rdata32 | (rdata32 << 16); |
| WRITE_VREG(HEVCD_MCRCC_CTL2, rdata32); |
| |
| /*Programme canvas1 */ |
| WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, |
| (16 << 8) | (1 << 1) | 0); |
| rdata32_2 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); |
| rdata32_2 = rdata32_2 & 0xffff; |
| rdata32_2 = rdata32_2 | (rdata32_2 << 16); |
| if (rdata32 == rdata32_2) { |
| rdata32_2 = |
| READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); |
| rdata32_2 = rdata32_2 & 0xffff; |
| rdata32_2 = rdata32_2 | (rdata32_2 << 16); |
| } |
| WRITE_VREG(HEVCD_MCRCC_CTL3, rdata32_2); |
| } else { /* P-PIC */ |
| WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, |
| (0 << 8) | (1 << 1) | 0); |
| rdata32 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); |
| rdata32 = rdata32 & 0xffff; |
| rdata32 = rdata32 | (rdata32 << 16); |
| WRITE_VREG(HEVCD_MCRCC_CTL2, rdata32); |
| |
| /*Programme canvas1*/ |
| rdata32 = |
| READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); |
| rdata32 = rdata32 & 0xffff; |
| rdata32 = rdata32 | (rdata32 << 16); |
| WRITE_VREG(HEVCD_MCRCC_CTL3, rdata32); |
| } |
| /*enable mcrcc progressive-mode */ |
| WRITE_VREG(HEVCD_MCRCC_CTL1, 0xff0); |
| return; |
| } |
| |
| static void config_mpred_hw(struct AVS2Decoder_s *dec) |
| { |
| uint32_t data32; |
| struct avs2_decoder *avs2_dec = &dec->avs2_dec; |
| struct avs2_frame_s *cur_pic = avs2_dec->hc.cur_pic; |
| struct avs2_frame_s *col_pic = avs2_dec->fref[0]; |
| int32_t mpred_mv_rd_start_addr; |
| int32_t mpred_curr_lcu_x; |
| int32_t mpred_curr_lcu_y; |
| int32_t mpred_mv_rd_end_addr; |
| int32_t above_en; |
| int32_t mv_wr_en; |
| int32_t mv_rd_en; |
| int32_t col_isIntra; |
| int mv_mem_unit; |
| if (avs2_dec->img.type != I_IMG) { |
| above_en = 1; |
| mv_wr_en = 1; |
| mv_rd_en = 1; |
| col_isIntra = 0; |
| } else { |
| above_en = 1; |
| mv_wr_en = 1; |
| mv_rd_en = 0; |
| col_isIntra = 0; |
| } |
| |
| mpred_mv_rd_start_addr = |
| col_pic->mpred_mv_wr_start_addr; |
| data32 = READ_VREG(HEVC_MPRED_CURR_LCU); |
| mpred_curr_lcu_x = data32 & 0xffff; |
| mpred_curr_lcu_y = (data32 >> 16) & 0xffff; |
| |
| mv_mem_unit = avs2_dec->lcu_size_log2 == 6 ? |
| 0x200 : (avs2_dec->lcu_size_log2 == 5 ? |
| 0x80 : 0x20); |
| |
| mpred_mv_rd_end_addr = |
| mpred_mv_rd_start_addr + |
| ((avs2_dec->lcu_x_num * |
| avs2_dec->lcu_y_num) * mv_mem_unit); |
| |
| avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, |
| "cur pic index %d col pic index %d\n", |
| cur_pic->index, col_pic->index); |
| |
| |
| WRITE_VREG(HEVC_MPRED_MV_WR_START_ADDR, |
| cur_pic->mpred_mv_wr_start_addr); |
| WRITE_VREG(HEVC_MPRED_MV_RD_START_ADDR, |
| col_pic->mpred_mv_wr_start_addr); |
| avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, |
| "[MPRED CO_MV] write 0x%x read 0x%x\n", |
| cur_pic->mpred_mv_wr_start_addr, |
| col_pic->mpred_mv_wr_start_addr); |
| |
| data32 = |
| ((avs2_dec->bk_img_is_top_field) << 13) | |
| ((avs2_dec->hd.background_picture_enable & 1) << 12) | |
| ((avs2_dec->hd.curr_RPS.num_of_ref & 7) << 8) | |
| ((avs2_dec->hd.b_pmvr_enabled & 1) << 6) | |
| ((avs2_dec->img.is_top_field & 1) << 5) | |
| ((avs2_dec->img.is_field_sequence & 1) << 4) | |
| ((avs2_dec->img.typeb & 7) << 1) | |
| (avs2_dec->hd.background_reference_enable & 0x1); |
| avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, |
| "HEVC_MPRED_CTRL9 <= 0x%x(num of ref %d)\n", |
| data32, avs2_dec->hd.curr_RPS.num_of_ref); |
| WRITE_VREG(HEVC_MPRED_CTRL9, data32); |
| |
| avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, |
| "%s: dis %d %d %d %d %d %d %d fref0_ref_poc %d %d %d %d %d %d %d\n", |
| __func__, |
| avs2_dec->fref[0]->imgtr_fwRefDistance, |
| avs2_dec->fref[1]->imgtr_fwRefDistance, |
| avs2_dec->fref[2]->imgtr_fwRefDistance, |
| avs2_dec->fref[3]->imgtr_fwRefDistance, |
| avs2_dec->fref[4]->imgtr_fwRefDistance, |
| avs2_dec->fref[5]->imgtr_fwRefDistance, |
| avs2_dec->fref[6]->imgtr_fwRefDistance, |
| avs2_dec->fref[0]->ref_poc[0], |
| avs2_dec->fref[0]->ref_poc[1], |
| avs2_dec->fref[0]->ref_poc[2], |
| avs2_dec->fref[0]->ref_poc[3], |
| avs2_dec->fref[0]->ref_poc[4], |
| avs2_dec->fref[0]->ref_poc[5], |
| avs2_dec->fref[0]->ref_poc[6] |
| ); |
| avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, |
| "pic_distance %d, imgtr_next_P %d\n", |
| avs2_dec->img.pic_distance, avs2_dec->img.imgtr_next_P); |
| |
| |
| WRITE_VREG(HEVC_MPRED_CUR_POC, avs2_dec->img.pic_distance); |
| WRITE_VREG(HEVC_MPRED_COL_POC, avs2_dec->img.imgtr_next_P); |
| |
| /*below MPRED Ref_POC_xx_Lx registers |
| must follow Ref_POC_xx_L0 -> |
| Ref_POC_xx_L1 in pair write order!!!*/ |
| WRITE_VREG(HEVC_MPRED_L0_REF00_POC, |
| avs2_dec->fref[0]->imgtr_fwRefDistance); |
| WRITE_VREG(HEVC_MPRED_L1_REF00_POC, |
| avs2_dec->fref[0]->ref_poc[0]); |
| |
| WRITE_VREG(HEVC_MPRED_L0_REF01_POC, |
| avs2_dec->fref[1]->imgtr_fwRefDistance); |
| WRITE_VREG(HEVC_MPRED_L1_REF01_POC, |
| avs2_dec->fref[0]->ref_poc[1]); |
| |
| WRITE_VREG(HEVC_MPRED_L0_REF02_POC, |
| avs2_dec->fref[2]->imgtr_fwRefDistance); |
| WRITE_VREG(HEVC_MPRED_L1_REF02_POC, |
| avs2_dec->fref[0]->ref_poc[2]); |
| |
| WRITE_VREG(HEVC_MPRED_L0_REF03_POC, |
| avs2_dec->fref[3]->imgtr_fwRefDistance); |
| WRITE_VREG(HEVC_MPRED_L1_REF03_POC, |
| avs2_dec->fref[0]->ref_poc[3]); |
| |
| WRITE_VREG(HEVC_MPRED_L0_REF04_POC, |
| avs2_dec->fref[4]->imgtr_fwRefDistance); |
| WRITE_VREG(HEVC_MPRED_L1_REF04_POC, |
| avs2_dec->fref[0]->ref_poc[4]); |
| |
| WRITE_VREG(HEVC_MPRED_L0_REF05_POC, |
| avs2_dec->fref[5]->imgtr_fwRefDistance); |
| WRITE_VREG(HEVC_MPRED_L1_REF05_POC, |
| avs2_dec->fref[0]->ref_poc[5]); |
| |
| WRITE_VREG(HEVC_MPRED_L0_REF06_POC, |
| avs2_dec->fref[6]->imgtr_fwRefDistance); |
| WRITE_VREG(HEVC_MPRED_L1_REF06_POC, |
| avs2_dec->fref[0]->ref_poc[6]); |
| |
| |
| WRITE_VREG(HEVC_MPRED_MV_RD_END_ADDR, |
| mpred_mv_rd_end_addr); |
| } |
| |
| static void config_dblk_hw(struct AVS2Decoder_s *dec) |
| { |
| /* |
| * Picture level de-block parameter configuration here |
| */ |
| struct avs2_decoder *avs2_dec = &dec->avs2_dec; |
| union param_u *rpm_param = &avs2_dec->param; |
| uint32_t data32; |
| |
| data32 = READ_VREG(HEVC_DBLK_CFG1); |
| data32 = (((data32 >> 20) & 0xfff) << 20) | |
| (((avs2_dec->input.sample_bit_depth == 10) |
| ? 0xa : 0x0) << 16) | /*[16 +: 4]: {luma_bd[1:0], |
| chroma_bd[1:0]}*/ |
| (((data32 >> 2) & 0x3fff) << 2) | |
| (((rpm_param->p.lcu_size == 6) |
| ? 0 : (rpm_param->p.lcu_size == 5) |
| ? 1 : 2) << 0);/*[ 0 +: 2]: lcu_size*/ |
| WRITE_VREG(HEVC_DBLK_CFG1, data32); |
| |
| data32 = (avs2_dec->img.height << 16) | |
| avs2_dec->img.width; |
| WRITE_VREG(HEVC_DBLK_CFG2, data32); |
| /* |
| [27 +: 1]: cross_slice_loopfilter_enable_flag |
| [26 +: 1]: loop_filter_disable |
| [25 +: 1]: useNSQT |
| [22 +: 3]: imgtype |
| [17 +: 5]: alpha_c_offset (-8~8) |
| [12 +: 5]: beta_offset (-8~8) |
| [ 6 +: 6]: chroma_quant_param_delta_u (-16~16) |
| [ 0 +: 6]: chroma_quant_param_delta_v (-16~16) |
| */ |
| data32 = ((avs2_dec->input.crossSliceLoopFilter |
| & 0x1) << 27) | |
| ((rpm_param->p.loop_filter_disable & 0x1) << 26) | |
| ((avs2_dec->input.useNSQT & 0x1) << 25) | |
| ((avs2_dec->img.type & 0x7) << 22) | |
| ((rpm_param->p.alpha_c_offset & 0x1f) << 17) | |
| ((rpm_param->p.beta_offset & 0x1f) << 12) | |
| ((rpm_param->p.chroma_quant_param_delta_cb & 0x3f) << 6) | |
| ((rpm_param->p.chroma_quant_param_delta_cr & 0x3f) << 0); |
| |
| WRITE_VREG(HEVC_DBLK_CFG9, data32); |
| avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, |
| "[c] cfgDBLK: crossslice(%d),lfdisable(%d),bitDepth(%d),lcuSize(%d),NSQT(%d)\n", |
| avs2_dec->input.crossSliceLoopFilter, |
| rpm_param->p.loop_filter_disable, |
| avs2_dec->input.sample_bit_depth, |
| avs2_dec->lcu_size, |
| avs2_dec->input.useNSQT); |
| avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, |
| "[c] cfgDBLK: alphaCOffset(%d),betaOffset(%d),quantDeltaCb(%d),quantDeltaCr(%d)\n", |
| rpm_param->p.alpha_c_offset, |
| rpm_param->p.beta_offset, |
| rpm_param->p.chroma_quant_param_delta_cb, |
| rpm_param->p.chroma_quant_param_delta_cr); |
| avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, |
| "[c] cfgDBLK: .done.\n"); |
| } |
| |
| static void config_sao_hw(struct AVS2Decoder_s *dec) |
| { |
| uint32_t data32; |
| struct avs2_decoder *avs2_dec = &dec->avs2_dec; |
| struct avs2_frame_s *cur_pic = avs2_dec->hc.cur_pic; |
| |
| int lcu_size = 64; |
| int mc_buffer_size_u_v = |
| cur_pic->lcu_total * lcu_size*lcu_size/2; |
| int mc_buffer_size_u_v_h = |
| (mc_buffer_size_u_v + 0xffff) >> 16;/*64k alignment*/ |
| |
| data32 = READ_VREG(HEVC_SAO_CTRL0); |
| data32 &= (~0xf); |
| data32 |= avs2_dec->lcu_size_log2; |
| avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, |
| "%s, lcu_size_log2 = %d, config HEVC_SAO_CTRL0 0x%x\n", |
| __func__, |
| avs2_dec->lcu_size_log2, |
| data32); |
| |
| WRITE_VREG(HEVC_SAO_CTRL0, data32); |
| |
| #ifndef AVS2_10B_MMU |
| if ((get_double_write_mode(dec) & 0x10) == 0) |
| WRITE_VREG(HEVC_CM_BODY_START_ADDR, cur_pic->mc_y_adr); |
| #endif |
| if (get_double_write_mode
|