| /* |
| * drivers/amlogic/amports/avs3.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/version.h> |
| #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) |
| #include <linux/dma-map-ops.h> |
| #else |
| #include <linux/dma-contiguous.h> |
| #endif |
| #include <linux/slab.h> |
| //#include <linux/amlogic/tee.h> |
| #include <uapi/linux/tee.h> |
| #include <linux/sched/clock.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 "avs3_global.h" |
| #include "../../../common/media_utils/media_utils.h" |
| //#define TMP_DEBUG |
| |
| //#define USE_FRONT_ISR_HANDLE_FOR_BACK |
| |
| #define FOR_S5 |
| #define PXP_DEBUG |
| #define USE_SIM_BUFSPEC |
| |
| //#define DEBUG_CMD |
| |
| #define MEM_NAME "codec_avs3" |
| /* #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 "../utils/vdec_feature.h" |
| #include "../utils/decoder_dma_alloc.h" |
| #include "../utils/vdec_profile.h" |
| |
| #define DYN_CACHE |
| #define I_ONLY_SUPPORT |
| #define MIX_STREAM_SUPPORT |
| //#define CONSTRAIN_MAX_BUF_NUM |
| |
| #define CO_MV_COMPRESS |
| |
| #include "vavs3.h" |
| #define HEVC_SHIFT_LENGTH_PROTECT 0x313a |
| #define HEVC_MPRED_CTRL4 0x324c |
| //#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 |
| |
| #define HEVC_CM_BODY_LENGTH2 0x3663 |
| #define HEVC_CM_HEADER_OFFSET2 0x3664 |
| #define HEVC_CM_HEADER_LENGTH2 0x3665 |
| |
| #define HEVC_ASSIST_MMU_MAP_ADDR 0x3009 |
| |
| #define HEVC_CM_HEADER_START_ADDR 0x3628 |
| #define HEVC_CM_HEADER_START_ADDR2 0x364a |
| #define HEVC_SAO_MMU_VH1_ADDR 0x363b |
| #define HEVC_SAO_MMU_VH0_ADDR 0x363a |
| #define HEVC_SAO_MMU_VH0_ADDR2 0x364d |
| #define HEVC_SAO_MMU_VH1_ADDR2 0x364e |
| |
| #define HEVC_SAO_MMU_DMA_CTRL2 0x364c |
| #define HEVC_SAO_MMU_STATUS2 0x3650 |
| #define HEVC_DW_VH0_ADDDR 0x365e |
| #define HEVC_DW_VH1_ADDDR 0x365f |
| |
| #define HEVC_SAO_CTRL9 0x362d |
| |
| /* |
| * AVS3_DEC_STATUS define |
| */ |
| /*internal*/ |
| #define AVS3_DEC_IDLE 0 |
| #define AVS3_SEQUENCE 1 |
| #define AVS3_I_PICTURE 2 |
| #define AVS3_PB_PICTURE 3 |
| #define AVS3_DISCARD_STARTCODE 4 |
| #define AVS3_DISCARD_NAL 4 |
| |
| #define AVS3_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 AVS3_HEAD_SEQ_READY 0x21 |
| #define AVS3_HEAD_PIC_I_READY 0x22 |
| #define AVS3_HEAD_PIC_PB_READY 0x23 |
| #define AVS3_HEAD_SEQ_END_READY 0x24 |
| #define AVS3_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 AVS3_DECODE_BUFEMPTY 0x33 |
| #define AVS3_DECODE_TIMEOUT 0x34 |
| #define AVS3_DECODE_OVER_SIZE 0x35 |
| #define AVS3_EOS 0x36 |
| |
| /*cmd*/ |
| #define AVS3_10B_DISCARD_NAL 0xf0 |
| #define AVS3_SEARCH_NEW_PIC 0xf1 |
| #define AVS3_ACTION_ERROR 0xfe |
| #define HEVC_ACTION_ERROR 0xfe |
| #define AVS3_ACTION_DONE 0xff |
| /*AVS3_DEC_STATUS end*/ |
| |
| //??? |
| #define HEVC_BE_DECODE_DATA 0xa0 |
| #define HEVC_BE_DECODE_DATA_DONE 0xb0 |
| #define HEVC_BE_DECODE_TIMEOUT 0xc0 |
| /*AVS3_BE_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_avs3" |
| |
| #define lock_buffer(dec, flags) \ |
| spin_lock_irqsave(&dec->buffer_lock, flags) |
| |
| #define unlock_buffer(dec, flags) \ |
| spin_unlock_irqrestore(&dec->buffer_lock, flags) |
| |
| #define lock_front_back(dec, flags) \ |
| spin_lock_irqsave(&dec->front_back_lock, flags) |
| |
| #define unlock_front_back(dec, flags) \ |
| spin_unlock_irqrestore(&dec->front_back_lock, flags) |
| |
| u32 debug_mask = 0xffffffff; |
| #define get_dbg_flag(dec) ((debug_mask & (1 << dec->index)) ? debug : 0) |
| |
| 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]; |
| #ifdef NEW_FB_CODE |
| static unsigned int max_process_time_back[MAX_DECODE_INSTANCE_NUM]; |
| static unsigned int run_count_back[MAX_DECODE_INSTANCE_NUM]; |
| #endif |
| 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; |
| #ifdef NEW_FB_CODE |
| static unsigned int decode_timeout_val_back = 200; |
| |
| static unsigned int efficiency_mode = 1; |
| |
| static void avs3_work_back(struct work_struct *work); |
| static void avs3_timeout_work_back(struct work_struct *work); |
| #endif |
| #endif |
| |
| static int start_decode_buf_level = 0x8000; |
| |
| static u32 work_buf_size; |
| |
| 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; |
| * 8, (1/8):(1/8) 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 trace_debug_mode = 7; |
| static u32 paral_alloc_buffer_mode = 1; |
| |
| static u32 mv_buf_dynamic_alloc; |
| |
| #define DRIVER_NAME "amvdec_avs3" |
| #define DRIVER_HEADER_NAME "amvdec_avs3_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_THRESHOLD 3 |
| |
| #define DUR2PTS(x) ((x)*90/96) |
| |
| struct AVS3Decoder_s; |
| static int vavs3_vf_states(struct vframe_states *states, void *); |
| static struct vframe_s *vavs3_vf_peek(void *); |
| static struct vframe_s *vavs3_vf_get(void *); |
| static void vavs3_vf_put(struct vframe_s *, void *); |
| static int vavs3_event_cb(int type, void *data, void *private_data); |
| static void set_vframe(struct AVS3Decoder_s *dec, |
| struct vframe_s *vf, struct avs3_frame_s *pic, u8 dummy); |
| |
| static int vavs3_stop(struct AVS3Decoder_s *dec); |
| static s32 vavs3_init(struct vdec_s *vdec); |
| static void vavs3_prot_init(struct AVS3Decoder_s *dec); |
| static int vavs3_local_init(struct AVS3Decoder_s *dec); |
| static void vavs3_put_timer_func(struct timer_list *timer); |
| static void dump_data(struct AVS3Decoder_s *dec, int size); |
| static unsigned char get_data_check_sum |
| (struct AVS3Decoder_s *dec, int size); |
| static struct avs3_frame_s *get_pic_by_index( |
| struct AVS3Decoder_s *dec, int index); |
| static int avs3_hw_ctx_restore(struct AVS3Decoder_s *dec); |
| static void dump_or_fill_phy_buffer(struct AVS3Decoder_s *dec, u32 phy_adr, u32 size, char *file, u8 flag, char *mark); |
| static void d_dump(struct AVS3Decoder_s *dec, unsigned int phy_adr, int size, |
| struct file *fp, loff_t *wr_off, u32 * total_check_sum, u8 print_flag); |
| |
| static const char vavs3_dec_id[] = "vavs3-dev"; |
| |
| #define PROVIDER_NAME "decoder.avs3" |
| #define MULTI_INSTANCE_PROVIDER_NAME "vdec.avs3" |
| |
| static const struct vframe_operations_s vavs3_vf_provider = { |
| .peek = vavs3_vf_peek, |
| .get = vavs3_vf_get, |
| .put = vavs3_vf_put, |
| .event_cb = vavs3_event_cb, |
| .vf_states = vavs3_vf_states, |
| }; |
| |
| static struct vframe_provider_s vavs3_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 |
| #define HDR_CUVA_MASK 0x40000000 |
| |
| 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 { |
| AVS3_BITS_8 = 8, /**< 8 bits */ |
| AVS3_BITS_10 = 10, /**< 10 bits */ |
| AVS3_BITS_12 = 12, /**< 12 bits */ |
| }; |
| |
| enum trace_debug_t { |
| TRACE_BASIC = 1, |
| TRACE_BUFFER = 2, |
| TRACE_PERFORMANCE_DETAIL = 4, |
| }; |
| |
| enum alloc_buffer_status_t { |
| BUFFER_INIT = 0, |
| BUFFER_ALLOCATING = 1, |
| BUFFER_ALLOCATE_DONE = 2, |
| }; |
| |
| /*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 AVS3_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 AVS3_10B_NV21 |
| #else |
| #define LOSLESS_COMPRESS_MODE |
| #endif |
| |
| #define DOUBLE_WRITE_YSTART_TEMP 0x02000000 |
| #define DOUBLE_WRITE_CSTART_TEMP 0x02900000 |
| |
| #if (defined DEBUG_UCODE_LOG) || (defined DEBUG_CMD) |
| //#define UCODE_LOG_BUF_SIZE (16 * 1024) |
| #define UCODE_LOG_BUF_SIZE (1024 * 1024) |
| #endif |
| |
| #ifdef DEBUG_CMD |
| static u32 debug_cmd_wait_count; |
| static u32 debug_cmd_wait_type; |
| #endif |
| |
| /* bit 0, disable backend |
| bit 1, start frontend only after last backend done (not pipeline front-back) |
| bit 2, do not loop buffer (use with bit[1] of 1) |
| bit 3, fill loop buffer 0 before starting front decoding |
| ## |
| bit[31:28],1: dump loop buffer at frontend data done for specific frame to file |
| bit[27:16], frame num |
| bit[31:28],2: dump frame count of frames to file |
| bit[27:16], frame count |
| bit[31:28],3: dump every frame and print checksum |
| bit[31:28] 8: dump loop buffer to file in dump_state() |
| */ |
| static u32 fbdebug_flag; |
| |
| static u32 debug; |
| |
| static u32 debug_again; |
| |
| u32 avs3_get_debug_flag(void) |
| { |
| return debug; |
| } |
| |
| bool is_avs3_print_param(void) |
| { |
| bool ret = false; |
| if (debug & AVS3_DBG_PRINT_PARAM) |
| ret = true; |
| return ret; |
| } |
| |
| inline bool is_avs3_print_bufmgr_detail(void) |
| { |
| bool ret = false; |
| if (debug & AVS3_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; |
| |
| static u32 dump_phy_adr; |
| static u32 dump_phy_size; |
| |
| #define AUX_BUF_ALIGN(adr) ((adr + 0xf) & (~0xf)) |
| static u32 cuva_buf_size = 512; |
| |
| #define DEBUG_REG |
| #ifdef DEBUG_REG |
| static void WRITE_VREG_DBG2(unsigned adr, unsigned val) |
| { |
| if (debug & AVS3_DBG_REG) { |
| unsigned adr_conv = dos_reg_compat_convert(adr); |
| pr_info("%s(%x, %x)\n", __func__, adr_conv, val); |
| } |
| if (adr != 0) |
| WRITE_VREG(adr, val); |
| |
| if (debug & AVS3_DBG_BUFMGR_DETAIL) { |
| if (adr == HEVC_ASSIST_SCRATCH_0) // && val == AVS3_ACTION_DONE) |
| pr_info("!!write HEVC_ASSIST_SCRATCH_0 %x\n", val); |
| } |
| } |
| |
| #undef WRITE_VREG |
| #define WRITE_VREG WRITE_VREG_DBG2 |
| #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 (MAX_PB_SIZE) |
| #define HEADER_FRAME_BUFFERS (FRAME_BUFFERS) |
| |
| #define FRAME_CONTEXTS_LOG2 2 |
| #define FRAME_CONTEXTS (1 << FRAME_CONTEXTS_LOG2) |
| /*buffer + header buffer + workspace*/ |
| |
| #ifdef NEW_FB_CODE |
| #define BMMU_IFBUF_SCALELUT_ID (0) |
| #define BMMU_IFBUF_VCPU_IMEM_ID (BMMU_IFBUF_SCALELUT_ID + 1) |
| #define BMMU_IFBUF_SYS_IMEM_ID (BMMU_IFBUF_VCPU_IMEM_ID + 1) |
| #define BMMU_IFBUF_LMEM0_ID (BMMU_IFBUF_SYS_IMEM_ID + 1) |
| #define BMMU_IFBUF_LMEM1_ID (BMMU_IFBUF_LMEM0_ID + 1) |
| #define BMMU_IFBUF_PARSER_SAO0_ID (BMMU_IFBUF_LMEM1_ID + 1) |
| #define BMMU_IFBUF_PARSER_SAO1_ID (BMMU_IFBUF_PARSER_SAO0_ID + 1) |
| #define BMMU_IFBUFF_MPRED_IMP0_ID (BMMU_IFBUF_PARSER_SAO1_ID + 1) |
| #define BMMU_IFBUFF_MPRED_IMP1_ID (BMMU_IFBUFF_MPRED_IMP0_ID + 1) |
| #define FB_LOOP_BUF_COUNT (BMMU_IFBUFF_MPRED_IMP1_ID + 1) |
| #else |
| #define FB_LOOP_BUF_COUNT 0 |
| #endif |
| |
| #define MV_USE_FIXED_BUF |
| #ifdef MV_USE_FIXED_BUF |
| #define MAX_BMMU_BUFFER_NUM (FB_LOOP_BUF_COUNT + (FRAME_BUFFERS + HEADER_FRAME_BUFFERS + 1)+1) |
| #define VF_BUFFER_IDX(n) (FB_LOOP_BUF_COUNT + n) |
| #define HEADER_BUFFER_IDX(n) (FB_LOOP_BUF_COUNT + FRAME_BUFFERS + n+1) |
| #define WORK_SPACE_BUF_ID (FB_LOOP_BUF_COUNT + FRAME_BUFFERS + HEADER_FRAME_BUFFERS+1) |
| #else |
| #define MAX_BMMU_BUFFER_NUM (FB_LOOP_BUF_COUNT + ((FRAME_BUFFERS*2)+HEADER_FRAME_BUFFERS+1)+1) |
| #define VF_BUFFER_IDX(n) (FB_LOOP_BUF_COUNT + n) |
| #define HEADER_BUFFER_IDX(n) (FB_LOOP_BUF_COUNT + FRAME_BUFFERS + n+1) |
| #define MV_BUFFER_IDX(n) (FB_LOOP_BUF_COUNT + (FRAME_BUFFERS * 2) + n+1) |
| #define WORK_SPACE_BUF_ID (FB_LOOP_BUF_COUNT + (FRAME_BUFFERS * 2) + HEADER_FRAME_BUFFERS+1) |
| //#define DW_HEADER_BUFFER_IDX(n) ((FRAME_BUFFERS * 3) + n+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 AVS3Decoder_s *dec, |
| struct avs3_frame_s *pic); |
| int avs3_prepare_display_buf(struct AVS3Decoder_s *dec, |
| int pos); |
| */ |
| |
| #ifdef NEW_FB_CODE |
| static u32 fb_ifbuf_num = 3; |
| /* |
| 0: single core mode |
| 1: front_back_mode |
| 2: front_back_test_mode |
| */ |
| static u32 front_back_mode = 1; |
| #endif |
| |
| struct BuffInfo_s { |
| u32 max_width; |
| u32 max_height; |
| u32 start_adr; |
| u32 end_adr; |
| struct buff_s ipp; |
| #ifdef NEW_FRONT_BACK_CODE |
| struct buff_s ipp1; |
| #endif |
| 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 sbac_top; |
| 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 AVS3_10B_MMU |
| struct buff_s mmu_vbh; |
| struct buff_s cm_header; |
| #endif |
| #ifdef AVS3_10B_MMU_DW |
| struct buff_s mmu_vbh_dw; |
| struct buff_s cm_header_dw; |
| #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 |
| #define DEC_RESULT_WAIT_BUFFER 11 |
| #ifdef NEW_FB_CODE |
| #define DEC_BACK_RESULT_NONE 0 |
| #define DEC_BACK_RESULT_DONE 1 |
| #define DEC_BACK_RESULT_TIMEOUT 2 |
| #define DEC_BACK_RESULT_FORCE_EXIT 10 |
| #endif |
| |
| static void avs3_work(struct work_struct *work); |
| struct loop_filter_info_n; |
| struct loopfilter; |
| struct segmentation; |
| |
| struct AVS3Decoder_s { |
| int pic_list_init_flag; |
| int pic_list_wait_alloc_done_flag; |
| unsigned char index; |
| spinlock_t front_back_lock; |
| spinlock_t buffer_lock; |
| struct device *cma_dev; |
| struct platform_device *platform_dev; |
| void (*vdec_cb)(struct vdec_s *, void *, int); |
| 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 vavs3_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 AVS3_10B_MMU |
| struct buff_s mc_buf_spec; |
| #endif |
| struct dec_sysinfo vavs3_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 (defined DEBUG_UCODE_LOG) || (defined DEBUG_CMD) |
| void *ucode_log_addr; |
| dma_addr_t ucode_log_phy_addr; |
| #endif |
| |
| #ifdef AVS3_10B_MMU |
| bool mmu_enable; |
| |
| u32 cuva_size; |
| void *cuva_addr; |
| dma_addr_t cuva_phy_addr; |
| |
| void *frame_mmu_map_addr; |
| dma_addr_t frame_mmu_map_phy_addr; |
| #endif |
| #ifdef AVS3_10B_MMU_DW |
| bool dw_mmu_enable; |
| void *dw_mmu_box; |
| void *dw_frame_mmu_map_addr; |
| dma_addr_t dw_frame_mmu_map_phy_addr; |
| #endif |
| unsigned int use_cma_flag; |
| |
| 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 AVS3_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 AVS3_10B_MMU |
| int cur_fb_idx_mmu; |
| #endif |
| struct avs3_decoder avs3_dec; |
| 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; |
| u32 endian; |
| dma_addr_t rdma_phy_adr; |
| unsigned *rdma_adr; |
| int hdr_flag; |
| |
| ulong rpm_mem_handle; |
| ulong lmem_phy_handle; |
| ulong frame_mmu_map_handle; |
| ulong frame_mmu_map_handle_1; |
| ulong frame_dw_mmu_map_handle; |
| ulong frame_dw_mmu_map_handle_1; |
| ulong ucode_log_handle; |
| ulong rdma_mem_handle; |
| ulong cuva_handle; |
| #ifdef NEW_FB_CODE |
| u32 front_back_mode; |
| int fb_ifbuf_num; |
| //int pic_wr_count; |
| //int pic_rd_count; |
| //struct PIC_s *decoded_PIC[MAX_REF_PIC_NUM]; |
| //u32 flush_count; |
| |
| /*init_fb_bufstate() for linux APIs*/ |
| struct work_struct work_back; |
| struct work_struct timeout_work_back; |
| u32 timeout_processing_back; |
| |
| void *frame_mmu_map_addr_1; |
| dma_addr_t frame_mmu_map_phy_addr_1; |
| void *mmu_box_1; |
| |
| void *dw_mmu_box_1; |
| void *dw_frame_mmu_map_addr_1; |
| dma_addr_t dw_frame_mmu_map_phy_addr_1; |
| |
| void *mmu_box_fb; |
| void *fb_buf_mmu0_addr; |
| void *fb_buf_mmu1_addr; |
| /**/ |
| void (*vdec_back_cb)(struct vdec_s *, void *, int); |
| void *vdec_back_cb_arg; |
| struct firmware_s *fw_back; |
| struct timer_list timer_back; |
| unsigned long int start_process_time_back; |
| unsigned int decode_timeout_count_back; |
| unsigned int timeout_num_back; |
| |
| int dec_back_result; |
| u32 dec_status_back; |
| struct mutex fb_mutex; |
| u32 mmu_fb_4k_number; |
| #endif |
| uint32_t ASSIST_MBOX0_IRQ_REG; |
| uint32_t ASSIST_MBOX0_CLR_REG; |
| uint32_t ASSIST_MBOX0_MASK; |
| uint32_t backend_ASSIST_MBOX0_IRQ_REG; |
| uint32_t backend_ASSIST_MBOX0_CLR_REG; |
| uint32_t backend_ASSIST_MBOX0_MASK; |
| |
| unsigned char print_buf[1024*16+16]; |
| int print_buf_len; |
| struct trace_decoder_name trace; |
| int has_i_frame; |
| struct mutex slice_header_lock; |
| }; |
| |
| static int compute_losless_comp_body_size( |
| struct AVS3Decoder_s *dec, int width, int height, |
| uint8_t is_bit_depth_10); |
| |
| static int avs3_mmu_page_num(struct AVS3Decoder_s *dec, |
| int pic_width, int pic_height, int is_bit_depth_10); |
| |
| static void avs3_work_implement(struct AVS3Decoder_s *dec); |
| |
| |
| #undef pr_info |
| #define pr_info printk |
| int avs3_debug(struct AVS3Decoder_s *dec, |
| int flag, const char *fmt, ...) |
| { |
| #define HEVC_PRINT_BUF 512 |
| unsigned char buf[HEVC_PRINT_BUF]; |
| int len = 0; |
| if (dec && dec->print_buf_len>0) { |
| dec->print_buf_len = 0; |
| pr_info("%s", dec->print_buf); |
| } |
| if (dec == NULL || |
| (flag == 0) || |
| ((debug_mask & |
| (1 << dec->index)) |
| && (debug & flag))) { |
| va_list args; |
| |
| va_start(args, fmt); |
| if (dec) |
| len = sprintf(buf, "[%d]", dec->index); |
| |
| #ifdef DEBUG_AMRISC |
| if (dec && dec->front_back_mode == 1) |
| len += sprintf(buf+len, "<%x,%x,%x>", READ_VREG(HEVC_ASSIST_SCRATCH_0), READ_VREG(HEVC_MPC_E), READ_VREG(HEVC_MPC_E_DBE)); |
| else |
| len += sprintf(buf+len, "<%x,%x>", READ_VREG(HEVC_ASSIST_SCRATCH_0), READ_VREG(HEVC_MPC_E)); |
| #endif |
| vsnprintf(buf + len, HEVC_PRINT_BUF - len, fmt, args); |
| //pr_debug("%s", buf); |
| pr_info("%s", buf); |
| va_end(args); |
| } |
| return 0; |
| } |
| |
| static void avs3_print_flush(struct AVS3Decoder_s *dec) |
| { |
| if (dec->print_buf_len>0) { |
| dec->print_buf_len = 0; |
| pr_info("%s", dec->print_buf); |
| } |
| } |
| |
| static int avs3_print_cont(struct AVS3Decoder_s *dec, |
| int flag, const char *fmt, ...) |
| { |
| //unsigned char buf[HEVC_PRINT_BUF]; |
| //int len = 0; |
| if (dec == NULL || |
| (flag == 0) || |
| ((debug_mask & |
| (1 << dec->index)) |
| && (debug & flag))) { |
| va_list args; |
| |
| va_start(args, fmt); |
| #if 0 |
| vsnprintf(buf + len, HEVC_PRINT_BUF - len, fmt, args); |
| pr_info("%s", buf); |
| #else |
| if (dec->print_buf_len<1024*16) |
| dec->print_buf_len += vsnprintf(dec->print_buf+dec->print_buf_len, |
| 1024*16-dec->print_buf_len, fmt, args); |
| else |
| pr_info("print_buf is full\n"); |
| #endif |
| 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(void) |
| { |
| if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) |
| return (MAX_FRAME_8K_NUM * 4); |
| |
| return (MAX_FRAME_4K_NUM * 4); |
| } |
| |
| static int get_compress_header_size(struct AVS3Decoder_s *dec) |
| { |
| int32_t pic_width = dec->avs3_dec.img.width; |
| int32_t pic_height = dec->avs3_dec.img.height; |
| |
| if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && |
| (IS_8K_SIZE(pic_width, pic_height))) |
| return MMU_COMPRESS_HEADER_SIZE_8K; |
| else if (IS_4K_SIZE(pic_width, pic_height)) |
| return MMU_COMPRESS_HEADER_SIZE_4K; |
| return MMU_COMPRESS_HEADER_SIZE_1080P; |
| } |
| |
| static void reset_process_time(struct AVS3Decoder_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 AVS3Decoder_s *dec) |
| { |
| dec->start_process_time = jiffies; |
| dec->decode_timeout_count = 0; |
| dec->last_lcu_idx = 0; |
| } |
| |
| static void update_decoded_pic(struct AVS3Decoder_s *dec); |
| |
| static void timeout_process(struct AVS3Decoder_s *dec) |
| { |
| struct avs3_decoder *avs3_dec = &dec->avs3_dec; |
| struct avs3_frame_s *cur_pic = avs3_dec->cur_pic; |
| dec->timeout_num++; |
| #ifdef NEW_FB_CODE |
| if (dec->front_back_mode == 1) { |
| amhevc_stop_f(); |
| } else |
| #endif |
| amhevc_stop(); |
| avs3_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); |
| } |
| |
| #ifdef NEW_FB_CODE |
| static void reset_process_time_back(struct AVS3Decoder_s *dec) |
| { |
| if (dec->start_process_time_back) { |
| unsigned int process_time = |
| 1000 * (jiffies - dec->start_process_time_back) / HZ; |
| dec->start_process_time_back = 0; |
| if (process_time > max_process_time_back[dec->index]) |
| max_process_time_back[dec->index] = process_time; |
| } |
| } |
| |
| static void start_process_time_back(struct AVS3Decoder_s *dec) |
| { |
| dec->start_process_time_back = jiffies; |
| dec->decode_timeout_count_back = 2; |
| } |
| |
| /* |
| static void restart_process_time_back(struct AVS3Decoder_s *dec) |
| { |
| dec->start_process_time_back = jiffies; |
| dec->decode_timeout_count_back = 2; |
| } |
| */ |
| static void timeout_process_back(struct AVS3Decoder_s *dec) |
| { |
| /* |
| * In this very timeout point,the vh265_work arrives, |
| * or in some cases the system become slow, then come |
| * this second timeout. In both cases we return. |
| */ |
| if (work_pending(&dec->work_back) || |
| work_busy(&dec->work_back) || |
| work_busy(&dec->timeout_work_back) || |
| work_pending(&dec->timeout_work_back)) { |
| pr_err("%s avs3[%d] work back pending, do nothing.\n",__func__, dec->index); |
| return; |
| } |
| |
| /* disable irq before handle timeout */ |
| WRITE_VREG(dec->backend_ASSIST_MBOX0_MASK, 0); |
| |
| avs3_print(dec, |
| 0, "%s decoder timeout\n", __func__); |
| dec->timeout_num_back++; |
| #if 0 |
| amhevc_stop(); |
| read_decode_info(dec); |
| hevc_print(dec, |
| 0, "%s decoder timeout\n", __func__); |
| check_pic_decoded_error(dec, |
| dec->pic_decoded_lcu_idx); |
| /*The current decoded frame is marked |
| error when the decode timeout*/ |
| if (dec->cur_pic != NULL) |
| dec->cur_pic->error_mark = 1; |
| dec->decoded_poc = dec->curr_POC; |
| dec->decoding_pic = NULL; |
| dec->dec_result = DEC_RESULT_DONE; |
| #endif |
| reset_process_time_back(dec); |
| |
| if (work_pending(&dec->work_back)) |
| return; |
| dec->dec_back_result = DEC_BACK_RESULT_TIMEOUT; |
| vdec_schedule_work(&dec->timeout_work_back); |
| } |
| #endif |
| |
| static u32 get_valid_double_write_mode(struct AVS3Decoder_s *dec) |
| { |
| u32 dw_mode; |
| |
| dw_mode = (dec->m_ins_flag && |
| ((double_write_mode & 0x80000000) == 0)) ? |
| dec->double_write_mode : |
| (double_write_mode & 0x7fffffff); |
| if (dw_mode & 0x20) { |
| if ((get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_T3) |
| && ((dw_mode & 0xf) == 2 || (dw_mode & 0xf) == 3)) |
| dw_mode = 0; |
| } |
| |
| return dw_mode; |
| } |
| |
| static int get_double_write_mode(struct AVS3Decoder_s *dec) |
| { |
| u32 valid_dw_mode = get_valid_double_write_mode(dec); |
| int w = dec->avs3_dec.img.width; |
| int h = dec->avs3_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; |
| } |
| |
| static inline void decoder_trace(char *name, int value, int flag) |
| { |
| if (trace_debug_mode & flag) |
| ATRACE_COUNTER(name, value); |
| } |
| |
| /* for double write buf alloc */ |
| static int get_double_write_mode_init(struct AVS3Decoder_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; |
| } |
| |
| //#define MAX_4K_NUM 0x1200 |
| #ifdef AVS3_10B_MMU |
| int avs3_alloc_mmu( |
| struct AVS3Decoder_s *dec, |
| int cur_buf_idx, |
| int pic_width, |
| int pic_height, |
| unsigned short bit_depth, |
| unsigned int *mmu_index_adr) |
| { |
| int cur_mmu_4k_number; |
| int bit_depth_10 = (bit_depth == AVS3_BITS_10); |
| int ret; |
| |
| cur_mmu_4k_number = avs3_mmu_page_num(dec, pic_width, pic_height, bit_depth_10); |
| if (cur_mmu_4k_number < 0) { |
| pr_err("%s: cur_mmu_4k_number 0x%x is error width %d height %d\n", |
| __func__, cur_mmu_4k_number, pic_width, pic_height); |
| return -1; |
| } |
| |
| avs3_print(dec, AVS3_DBG_BUFMGR_MORE, |
| "%s decoder_mmu_box_alloc_idx index=%d mmu_4k_number %d\n", |
| __func__, cur_buf_idx, cur_mmu_4k_number); |
| |
| decoder_trace(dec->trace.decode_header_memory_time_name, TRACE_HEADER_MEMORY_START, TRACE_BASIC); |
| ret = decoder_mmu_box_alloc_idx( |
| dec->mmu_box, |
| cur_buf_idx, |
| cur_mmu_4k_number, |
| mmu_index_adr); |
| decoder_trace(dec->trace.decode_header_memory_time_name, TRACE_HEADER_MEMORY_END, TRACE_BASIC); |
| |
| return ret; |
| } |
| #endif |
| |
| #ifdef AVS3_10B_MMU_DW |
| int avs3_alloc_dw_mmu( |
| struct AVS3Decoder_s *dec, |
| int cur_buf_idx, |
| int pic_width, |
| int pic_height, |
| unsigned short bit_depth, |
| unsigned int *mmu_index_adr) |
| { |
| int cur_mmu_4k_number; |
| int bit_depth_10 = (bit_depth == AVS3_BITS_10); |
| int ret; |
| |
| cur_mmu_4k_number = avs3_mmu_page_num(dec, pic_width, pic_height, bit_depth_10); |
| if (cur_mmu_4k_number < 0) { |
| return -1; |
| } |
| |
| avs3_print(dec, AVS3_DBG_BUFMGR_MORE, |
| "%s decoder_mmu_box_alloc_idx index=%d mmu_4k_number %d\n", |
| __func__, cur_buf_idx, cur_mmu_4k_number); |
| |
| decoder_trace(dec->trace.decode_header_memory_time_name, TRACE_HEADER_MEMORY_START, TRACE_BASIC); |
| ret = decoder_mmu_box_alloc_idx( |
| dec->dw_mmu_box, |
| cur_buf_idx, |
| cur_mmu_4k_number, |
| mmu_index_adr); |
| decoder_trace(dec->trace.decode_header_memory_time_name, TRACE_HEADER_MEMORY_END, TRACE_BASIC); |
| |
| return ret; |
| } |
| #endif |
| |
| static int get_free_buf_count(struct AVS3Decoder_s *dec) |
| { |
| struct avs3_decoder *avs3_dec = &dec->avs3_dec; |
| int ii; |
| int count = 0; |
| for (ii = 0; ii < avs3_dec->max_pb_size; ii++) { |
| if (avs3_dec->pic_pool[ii].buf_cfg.used == 0) |
| count++; |
| } |
| return count; |
| } |
| |
| #ifdef CONSTRAIN_MAX_BUF_NUM |
| static int get_vf_ref_only_buf_count(struct AVS3Decoder_s *dec) |
| { |
| struct avs3_decoder *avs3_dec = &dec->avs3_dec; |
| int ii; |
| int count = 0; |
| for (ii = 0; ii < avs3_dec->max_pb_size; ii++) { |
| if (avs3_dec->pic_pool[ii].buf_cfg.used > 0 && |
| avs3_dec->pic_pool[ii].buf_cfg.vf_ref > 0 && |
| #ifdef NEW_FRONT_BACK_CODE |
| avs3_dec->pic_pool[ii].buf_cfg.backend_ref == 0 && /*?? why need it in case0763, |
| used is supposed to be 1 if backend_ref is not 0*/ |
| #endif |
| avs3_dec->pic_pool[ii].is_ref == 0 && |
| avs3_dec->pic_pool[ii].need_for_out == 0 |
| ) { |
| count++; |
| } |
| } |
| return count; |
| } |
| |
| static int get_used_buf_count(struct AVS3Decoder_s *dec) |
| { |
| struct avs3_decoder *avs3_dec = &dec->avs3_dec; |
| int ii; |
| int count = 0; |
| for (ii = 0; ii < avs3_dec->max_pb_size; ii++) { |
| if (avs3_dec->pic_pool[ii].buf_cfg.used > 0) |
| count++; |
| } |
| return count; |
| } |
| #endif |
| int avs3_dec_init(struct AVS3Decoder_s *dec, struct BuffInfo_s *buf_spec_i, |
| struct buff_s *mc_buf_i) { |
| |
| dec->frame_count = 0; |
| #ifdef AVS3_10B_MMU |
| dec->cur_fb_idx_mmu = INVALID_IDX; |
| #endif |
| |
| /* private init */ |
| dec->work_space_buf = buf_spec_i; |
| #ifndef AVS3_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->has_i_frame = 0; |
| dec->bufmgr_error_count = 0; |
| #ifdef NEW_FB_CODE |
| dec->start_process_time_back = 0; |
| dec->decode_timeout_count_back = 0; |
| dec->timeout_num_back = 0; |
| #endif |
| 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 avs3_version = 201602101; |
| static u32 radr; |
| static u32 rval; |
| static u32 pop_shorts; |
| /*dbg_cmd[3:0]: |
| 2, dump phy address of (dbg_cmd[31:4]<<4) |
| */ |
| static u32 dbg_cmd; |
| static u32 dbg_skip_decode_index; |
| /* |
| * bit 0~3, for HEVCD_IPP_AXIIF_CONFIG endian config |
| * bit 8~23, for HEVC_SAO_CTRL1 endian config |
| */ |
| static u32 endian; |
| #define HEVC_CONFIG_BIG_ENDIAN ((0x880 << 8) | 0x8) |
| #define HEVC_CONFIG_LITTLE_ENDIAN ((0xff0 << 8) | 0xf) |
| |
| #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: avs3_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 = 5; |
| /* |
| 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 = (MAX_NUM_REF_PICS); |
| |
| static u32 run_ready_min_buf_num = 1; |
| |
| static DEFINE_MUTEX(vavs3_mutex); |
| |
| #define HEVC_DEC_STATUS_REG HEVC_ASSIST_SCRATCH_0 |
| #define HEVC_RPM_BUFFER HEVC_ASSIST_SCRATCH_1 |
| #define AVS3_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 AVS3_10B_MMU |
| #define AVS3_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 AVS3_CUVA_ADR HEVC_ASSIST_SCRATCH_A |
| //#define AVS3_CUVA_DATA_SIZE HEVC_ASSIST_SCRATCH_B |
| /*same as simulation*/ |
| #define HEVC_DECODE_COUNT HEVC_ASSIST_SCRATCH_A |
| #define HEVC_DECODE_SIZE HEVC_ASSIST_SCRATCH_B |
| /**/ |
| |
| #define AVS3_SBAC_TOP_BUFFER HEVC_ASSIST_SCRATCH_C |
| #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_EFFICIENCY_MODE HEVC_ASSIST_SCRATCH_L |
| /*!!!*/ |
| #define AVS3_CUVA_ADR HEVC_ASSIST_SCRATCH_M |
| #define AVS3_CUVA_DATA_SIZE HEVC_ASSIST_SCRATCH_N |
| #define HEVC_DECODE_PIC_BEGIN HEVC_ASSIST_SCRATCH_M |
| #define DEBUG_REG1 HEVC_ASSIST_SCRATCH_G |
| #define DEBUG_REG2 HEVC_ASSIST_SCRATCH_H |
| |
| #if (defined DEBUG_UCODE_LOG) || (defined DEBUG_CMD) |
| #define HEVC_DBG_LOG_ADR HEVC_ASSIST_SCRATCH_5 |
| #ifdef DEBUG_CMD |
| #define HEVC_D_ADR HEVC_ASSIST_SCRATCH_4 |
| #endif |
| #endif |
| |
| #ifdef NEW_FRONT_BACK_CODE |
| #define HEVC_DEC_STATUS_DBE HEVC_ASSIST_SCRATCH_W |
| #define PIC_DECODE_COUNT_DBE HEVC_ASSIST_SCRATCH_X |
| #define DEBUG_REG1_DBE HEVC_ASSIST_SCRATCH_Y |
| #define DEBUG_REG2_DBE HEVC_ASSIST_SCRATCH_Z |
| #endif |
| /* |
| 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 |
| |
| #ifdef NEW_FRONT_BACK_CODE |
| #define HEVC_DEC_STATUS_DBE HEVC_ASSIST_SCRATCH_W |
| #define PIC_DECODE_COUNT_DBE HEVC_ASSIST_SCRATCH_X |
| #define DEBUG_REG1_DBE HEVC_ASSIST_SCRATCH_Y |
| #define DEBUG_REG2_DBE HEVC_ASSIST_SCRATCH_Z |
| |
| #define EE_ASSIST_MBOX0_IRQ_REG 0x3f70 |
| #define EE_ASSIST_MBOX0_CLR_REG 0x3f71 |
| #define EE_ASSIST_MBOX0_MASK 0x3f72 |
| #endif |
| |
| #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) |
| |
| /* necessary 4K page size align for t7/t3 decoder and after */ |
| #define WORKBUF_ALIGN(addr) (ALIGN(addr, PAGE_SIZE)) |
| |
| #define WORK_BUF_SPEC_NUM 6 |
| static struct BuffInfo_s amvavs3_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, |
| }, |
| #ifdef NEW_FRONT_BACK_CODE |
| .ipp1 = { |
| // IPP work space calculation : 4096 * (Y+CbCr+Flags) = 12k, round to 16k |
| .buf_size = 0x1e00, |
| }, |
| #endif |
| .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, |
| }, |
| .sbac_top = { |
| // DAALA TOP STORE AREA - 224 Bytes (use 256 Bytes for LPDDR4) per 128. Total 4096/128*256 = 0x2000 |
| .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 AVS3_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 |
| #ifdef AVS3_10B_MMU_DW |
| .mmu_vbh_dw = { |
| .buf_size = DW_VBH_BUF_SIZE_1080P, //2*16*2304/4, 4K |
| }, |
| #if 0 |
| .cm_header_dw = { |
| .buf_size = MMU_COMPRESS_HEADER_SIZE_DW*17, // 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 = 0x600 * 2, |
| } |
| }, |
| { |
| .max_width = 4096, |
| .max_height = 2304, |
| .ipp = { |
| /* IPP work space calculation : |
| 4096 * (Y+CbCr+Flags) = 12k, round to 16k */ |
| .buf_size = 0x4000, |
| }, |
| #ifdef NEW_FRONT_BACK_CODE |
| .ipp1 = { |
| // IPP work space calculation : 4096 * (Y+CbCr+Flags) = 12k, round to 16k |
| .buf_size = 0x4000, |
| }, |
| #endif |
| .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 */ |
| // RLP STORE AREA - Max 64 L0 + 64 L1 RLP, each has 32 bytes, total 0x1000 bytes |
| .buf_size = 0x1000, |
| }, |
| .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, |
| }, |
| .sbac_top = { |
| // DAALA TOP STORE AREA - 224 Bytes (use 256 Bytes for LPDDR4) per 128. Total 4096/128*256 = 0x2000 |
| .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 = { .buf_size = 0x40000, }, |
| .dblk_data = { .buf_size = 0x80000, }, |
| .dblk_data2 = { .buf_size = 0x80000, }, |
| #ifdef AVS3_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 |
| #ifdef AVS3_10B_MMU_DW |
| .mmu_vbh_dw = { |
| .buf_size = DW_VBH_BUF_SIZE_4K, //2*16*2304/4, 4K |
| }, |
| #if 0 |
| .cm_header_dw = { |
| .buf_size = MMU_COMPRESS_HEADER_SIZE_DW*17, // 0x44000 = ((1088*2*1024*4)/32/4)*(32/8) |
| }, |
| #endif |
| #endif |
| .mpred_above = { |
| .buf_size = 0x8000, /* 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 = 0x600 * 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, |
| }, |
| #ifdef NEW_FRONT_BACK_CODE |
| .ipp1 = { |
| // IPP work space calculation : 4096 * (Y+CbCr+Flags) = 12k, round to 16k |
| .buf_size = 0x4000 * 2, |
| }, |
| #endif |
| #ifdef USE_SIM_BUFSPEC |
| .sao_abv = { |
| .buf_size = 0x30000*2, |
| }, |
| .sao_vb = { |
| .buf_size = 0x30000*2, |
| }, |
| |
| #else |
| .sao_abv = { |
| .buf_size = 0, |
| }, |
| .sao_vb = { |
| .buf_size = 0, |
| }, |
| #endif |
| .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*/ |
| // RLP STORE AREA - Max 64 L0 + 64 L1 RLP, each has 32 bytes, total 0x1000 bytes |
| .buf_size = 0x1000, |
| }, |
| .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, |
| }, |
| .sbac_top = { |
| // DAALA TOP STORE AREA - 224 Bytes (use 256 Bytes for LPDDR4) per 128. Total 4096/128*256 = 0x2000 |
| .buf_size = 0x2000 * 2, |
| }, |
| #ifdef USE_SIM_BUFSPEC |
| .sao_up = { |
| // SAO UP STORE AREA - Max 640(10240/16) LCU, each has 16 bytes total 0x2800 bytes |
| .buf_size = 0x2800*2, |
| }, |
| #else |
| .sao_up = { |
| /*SAO UP STORE AREA - Max 640(10240/16) LCU, each has 16 bytes i |
| total 0x2800 bytes*/ |
| .buf_size = 0, |
| }, |
| #endif |
| .swap_buf = { |
| /*256cyclex64bit = 2K bytes 0x800 (only 144 cycles valid)*/ |
| .buf_size = 0x800, |
| }, |
| .swap_buf2 = { |
| .buf_size = 0x800, |
| }, |
| #ifdef USE_SIM_BUFSPEC |
| .scalelut = { |
| // support up to 32 SCALELUT 1024x32 = 32Kbytes (0x8000) |
| .buf_size = 0x8000*2, |
| }, |
| #else |
| .scalelut = { |
| /*support up to 32 SCALELUT 1024x32 = 32Kbytes (0x8000)*/ |
| .buf_size = 0, |
| }, |
| #endif |
| .dblk_para = { .buf_size = 0x40000*2, }, |
| .dblk_data = { .buf_size = 0x80000*2, }, |
| .dblk_data2 = { .buf_size = 0x80000*2, }, |
| #ifdef AVS3_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 |
| #ifdef AVS3_10B_MMU_DW |
| .mmu_vbh_dw = { |
| .buf_size = DW_VBH_BUF_SIZE_8K, //2*16*2304/4, 4K |
| }, |
| #if 0 |
| .cm_header_dw = { |
| .buf_size = MMU_COMPRESS_HEADER_SIZE_DW*17, // 0x44000 = ((1088*2*1024*4)/32/4)*(32/8) |
| }, |
| #endif |
| #endif |
| .mpred_above = { |
| .buf_size = 0x8000*2, |
| }, |
| #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 = 0x600 * 2, |
| } |
| }, |
| |
| //large buf size for debugging only |
| { |
| .max_width = 4096 * 2, |
| .max_height = 2304 * 2, |
| .ipp = { |
| /*IPP work space calculation : 4096 * (Y+CbCr+Flags) = 12k, |
| round to 16k*/ |
| .buf_size = 0x4000 * 4, |
| }, |
| #ifdef NEW_FRONT_BACK_CODE |
| .ipp1 = { |
| // IPP work space calculation : 4096 * (Y+CbCr+Flags) = 12k, round to 16k |
| .buf_size = 0x4000 * 4, |
| }, |
| #endif |
| #ifdef USE_SIM_BUFSPEC |
| .sao_abv = { |
| .buf_size = 0x30000*4, |
| }, |
| .sao_vb = { |
| .buf_size = 0x30000*4, |
| }, |
| #else |
| .sao_abv = { |
| .buf_size = 0, |
| }, |
| .sao_vb = { |
| .buf_size = 0, |
| }, |
| #endif |
| .short_term_rps = { |
| /*SHORT_TERM_RPS - Max 64 set, 16 entry every set, |
| total 64x16x2 = 2048 bytes (0x800)*/ |
| .buf_size = 0x800*4 |
| }, |
| .rcs = { |
| /*RCS STORE AREA - Max 16 RCS, each has 32 bytes, |
| total 0x0400 bytes*/ |
| // RLP STORE AREA - Max 64 L0 + 64 L1 RLP, each has 32 bytes, total 0x1000 bytes |
| .buf_size = 0x1000*4, |
| }, |
| .sps = { |
| /*SPS STORE AREA - Max 16 SPS, each has 0x80 bytes, |
| total 0x0800 bytes*/ |
| .buf_size = 0x800*4, |
| }, |
| .pps = { |
| /*PPS STORE AREA - Max 64 PPS, each has 0x80 bytes, total |
| 0x2000 bytes*/ |
| .buf_size = 0x2000*2, |
| }, |
| .sbac_top = { |
| // DAALA TOP STORE AREA - 224 Bytes (use 256 Bytes for LPDDR4) per 128. Total 4096/128*256 = 0x2000 |
| .buf_size = 0x2000 * 4, |
| }, |
| #ifdef USE_SIM_BUFSPEC |
| .sao_up = { |
| // SAO UP STORE AREA - Max 640(10240/16) LCU, each has 16 bytes total 0x2800 bytes |
| .buf_size = 0x2800*4, |
| }, |
| #else |
| .sao_up = { |
| /*SAO UP STORE AREA - Max 640(10240/16) LCU, each has 16 bytes i |
| total 0x2800 bytes*/ |
| .buf_size = 0, |
| }, |
| #endif |
| .swap_buf = { |
| /*256cyclex64bit = 2K bytes 0x800 (only 144 cycles valid)*/ |
| .buf_size = 0x800*4, |
| }, |
| .swap_buf2 = { |
| .buf_size = 0x800*4, |
| }, |
| #ifdef USE_SIM_BUFSPEC |
| .scalelut = { |
| // support up to 32 SCALELUT 1024x32 = 32Kbytes (0x8000) |
| .buf_size = 0x8000*2, |
| }, |
| #else |
| .scalelut = { |
| /*support up to 32 SCALELUT 1024x32 = 32Kbytes (0x8000)*/ |
| .buf_size = 0, |
| }, |
| #endif |
| .dblk_para = { .buf_size = 0x40000*4, }, |
| .dblk_data = { .buf_size = 0x80000*4, }, |
| .dblk_data2 = { .buf_size = 0x80000*4, }, |
| #ifdef AVS3_10B_MMU |
| .mmu_vbh = { |
| .buf_size = VBH_BUF_SIZE_8K*2, /*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 |
| #ifdef AVS3_10B_MMU_DW |
| .mmu_vbh_dw = { |
| .buf_size = DW_VBH_BUF_SIZE_8K*2, //2*16*2304/4, 4K |
| }, |
| #if 0 |
| .cm_header_dw = { |
| .buf_size = MMU_COMPRESS_HEADER_SIZE_DW*17, // 0x44000 = ((1088*2*1024*4)/32/4)*(32/8) |
| }, |
| #endif |
| #endif |
| .mpred_above = { |
| .buf_size = 0x8000*4, |
| }, |
| #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 = 0x600 * 2, |
| } |
| } |
| |
| }; |
| |
| #define IS_8K_SIZE(w, h) (((w) * (h)) > MAX_SIZE_4K) |
| #define IS_4K_SIZE(w, h) (((w) * (h)) > (1920*1088)) |
| |
| static u32 get_mv_mem_unit(int lcu_size_log2) |
| { |
| u32 mv_mem_unit; |
| //lcu_size_log2 == 6 ? 0x200 : lcu_size_log2 == 5 ? 0x80 : 0x20; //avs2 |
| //mv_mem_unit = lcu_size_log2 == 7 ? 256 : lcu_size_log2 == 6 ? 64 : 16; |
| mv_mem_unit = lcu_size_log2 == 7 ? 512 : lcu_size_log2 == 6 ? 128 : 32; |
| return mv_mem_unit; |
| } |
| |
| #ifndef MV_USE_FIXED_BUF |
| |
| static uint32_t get_mv_buf_size(struct AVS3Decoder_s *dec, int width, int height) { |
| struct avs3_decoder *avs3_dec = &dec->avs3_dec; |
| uint32_t size; |
| if (mv_buf_dynamic_alloc == 1) { |
| int mv_mem_unit = |
| get_mv_mem_unit(avs3_dec->lcu_size_log2); |
| |
| int32_t pic_width = avs3_dec->img.width; |
| int32_t pic_height = avs3_dec->img.height; |
| int32_t lcu_size = 1<<avs3_dec->lcu_size_log2; |
| int32_t pic_width_lcu = ( pic_width %lcu_size ) ? pic_width /lcu_size + 1 : pic_width /lcu_size; |
| int32_t pic_height_lcu = ( pic_height %lcu_size ) ? pic_height/lcu_size + 1 : pic_height/lcu_size; |
| int32_t lcu_total =pic_width_lcu*pic_height_lcu; |
| int new_size = lcu_total * 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 |
| |
| static void config_hevc_irq_num(struct AVS3Decoder_s *dec) |
| { |
| #ifdef NEW_FB_CODE |
| if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_S5) { |
| dec->ASSIST_MBOX0_IRQ_REG = EE_ASSIST_MBOX0_IRQ_REG; |
| dec->ASSIST_MBOX0_CLR_REG = EE_ASSIST_MBOX0_CLR_REG; |
| dec->ASSIST_MBOX0_MASK = EE_ASSIST_MBOX0_MASK; |
| dec->backend_ASSIST_MBOX0_IRQ_REG = HEVC_ASSIST_MBOX0_IRQ_REG; |
| dec->backend_ASSIST_MBOX0_CLR_REG = HEVC_ASSIST_MBOX0_CLR_REG; |
| dec->backend_ASSIST_MBOX0_MASK = HEVC_ASSIST_MBOX0_MASK; |
| } else { |
| dec->ASSIST_MBOX0_IRQ_REG = HEVC_ASSIST_MBOX0_IRQ_REG; |
| dec->ASSIST_MBOX0_CLR_REG = HEVC_ASSIST_MBOX0_CLR_REG; |
| dec->ASSIST_MBOX0_MASK = HEVC_ASSIST_MBOX0_MASK; |
| dec->backend_ASSIST_MBOX0_IRQ_REG = EE_ASSIST_MBOX0_IRQ_REG; |
| dec->backend_ASSIST_MBOX0_CLR_REG = EE_ASSIST_MBOX0_CLR_REG; |
| dec->backend_ASSIST_MBOX0_MASK = EE_ASSIST_MBOX0_MASK; |
| } |
| #else |
| dec->ASSIST_MBOX0_IRQ_REG = HEVC_ASSIST_MBOX0_IRQ_REG; |
| dec->ASSIST_MBOX0_CLR_REG = HEVC_ASSIST_MBOX0_CLR_REG; |
| dec->ASSIST_MBOX0_MASK = HEVC_ASSIST_MBOX0_MASK; |
| #endif |
| } |
| |
| #ifdef NEW_FB_CODE |
| #include "avs3_fb_hw.c" |
| |
| /*simulation code: if (dec_status == HEVC_DECPIC_DATA_DONE) {*/ |
| static int front_decpic_done_update(struct AVS3Decoder_s *dec, uint8_t reset_flag) |
| { |
| struct avs3_decoder *avs3_dec = &dec->avs3_dec; |
| avs3_frame_t *cur_pic = avs3_dec->cur_pic; |
| int j; |
| if (debug & AVS3_DBG_PRINT_PIC_LIST) { |
| print_pic_pool(avs3_dec, "before inc backend_ref"); |
| |
| avs3_print_cont(dec, 0, "pic_cfg index %d, list0 index ", cur_pic->index); |
| for (j = 0; j < cur_pic->list0_num_refp; j++) |
| avs3_print_cont(dec, 0, "%d ", cur_pic->list0_index[j]); |
| avs3_print_cont(dec, 0, "list1 index "); |
| for (j = 0; j < cur_pic->list1_num_refp; j++) |
| avs3_print_cont(dec, 0, "%d ", cur_pic->list1_index[j]); |
| avs3_print(dec, 0, "\n"); |
| } |
| cur_pic->backend_ref = 1; |
| for (j = 0; j < cur_pic->list0_num_refp; j++) |
| avs3_dec->pic_pool[cur_pic->list0_index[j]].buf_cfg.backend_ref++; |
| for (j = 0; j < cur_pic->list1_num_refp; j++) |
| avs3_dec->pic_pool[cur_pic->list1_index[j]].buf_cfg.backend_ref++; |
| |
| if (debug & AVS3_DBG_PRINT_PIC_LIST) |
| print_pic_pool(avs3_dec, "after inc backend_ref"); |
| |
| dec->avs3_dec.cur_pic->back_done_mark = 0; |
| |
| if (dec->front_back_mode == 1) { |
| if (fbdebug_flag & 0x70000000) { |
| u8 cmd = (fbdebug_flag >> 28) & 0x7; |
| u32 dump_c = (fbdebug_flag >> 16) & 0xfff; |
| if ((cmd == 3) || |
| (cmd == 1 && dump_c == avs3_dec->frontend_decoded_count) || |
| (cmd == 2 && avs3_dec->frontend_decoded_count < dump_c)) |
| dump_loop_buffer(dec, avs3_dec->frontend_decoded_count, cmd ==1 || cmd == 2); |
| } |
| |
| if (fbdebug_flag & 0x4) { |
| copy_loopbufs_ptr(&avs3_dec->fr, &avs3_dec->init_fr); |
| print_loopbufs_ptr(dec, "fr", &avs3_dec->fr); |
| } |
| else { |
| copy_loopbufs_ptr(&avs3_dec->p_fr, &avs3_dec->fr); |
| read_bufstate_front(avs3_dec); |
| avs3_print(dec, PRINT_FLAG_VDEC_DETAIL, |
| "update fr from loop buf register\n"); |
| |
| print_loopbufs_ptr2(dec, "fr", &avs3_dec->p_fr, &avs3_dec->fr); |
| } |
| |
| WRITE_VREG(HEVC_ASSIST_FB_PIC_CLR, 1); |
| |
| //WRITE_VREG(HEVC_DEC_STATUS_REG, AVS3_DEC_IDLE); |
| avs3_dec->frontend_decoded_count++; |
| avs3_dec->next_be_decode_pic[avs3_dec->fb_wr_pos] = avs3_dec->cur_pic; |
| avs3_print(dec, PRINT_FLAG_VDEC_DETAIL, "set pic index %d to fb_wr_pos %d\n", |
| avs3_dec->cur_pic->index, avs3_dec->fb_wr_pos); |
| mutex_lock(&dec->fb_mutex); |
| avs3_dec->fb_wr_pos++; |
| if (avs3_dec->fb_wr_pos >= dec->fb_ifbuf_num) |
| avs3_dec->fb_wr_pos = 0; |
| |
| if (avs3_dec->fb_wr_pos == avs3_dec->fb_rd_pos) { |
| avs3_dec->wait_working_buf = 1; |
| avs3_print(dec, PRINT_FLAG_VDEC_DETAIL, |
| "set next fb_wr_pos %d, fb_rd_pos %d, set wait_working_buf %d\n", avs3_dec->fb_wr_pos, avs3_dec->fb_rd_pos, avs3_dec->wait_working_buf); |
| } else { |
| avs3_print(dec, PRINT_FLAG_VDEC_DETAIL, |
| "set next fb_wr_pos %d, fb_rd_pos %d, wait_working_buf %d\n", avs3_dec->fb_wr_pos, avs3_dec->fb_rd_pos, avs3_dec->wait_working_buf); |
| } |
| mutex_unlock(&dec->fb_mutex); |
| #if 0 //def RESET_FRONT_PER_PICTURE |
| if (reset_flag) { |
| /*not multi pictures in one packe*/ |
| amhevc_stop_f(); |
| //save_stream_context(dec->work_space_buf->swap_buf.buf_start); |
| } |
| #endif |
| } else { |
| avs3_dec->frontend_decoded_count++; |
| avs3_dec->next_be_decode_pic[avs3_dec->fb_wr_pos] = avs3_dec->cur_pic; |
| mutex_lock(&dec->fb_mutex); |
| avs3_dec->fb_wr_pos++; |
| if (avs3_dec->fb_wr_pos >= dec->fb_ifbuf_num) |
| avs3_dec->fb_wr_pos = 0; |
| |
| if (avs3_dec->fb_wr_pos == avs3_dec->fb_rd_pos) { |
| avs3_dec->wait_working_buf = 1; |
| avs3_print(dec, PRINT_FLAG_VDEC_DETAIL, |
| "fb_wr_pos %d fb_rd_pos %d, set wait_working_buf = 1\n", avs3_dec->fb_wr_pos, avs3_dec->fb_rd_pos); |
| } else { |
| avs3_print(dec, PRINT_FLAG_VDEC_DETAIL, |
| "fb_wr_pos %d fb_rd_pos %d\n", avs3_dec->fb_wr_pos, avs3_dec->fb_rd_pos); |
| } |
| mutex_unlock(&dec->fb_mutex); |
| if (reset_flag) /*not multi pictures in one packe*/ |
| amhevc_stop(); |
| } |
| return 0; |
| } |
| |
| #endif |
| |
| /*Losless compression body buffer size 4K per 64x32 (jt)*/ |
| static int compute_losless_comp_body_size(struct AVS3Decoder_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; |
| bsize = (is_bit_depth_10 ? 4096 : 3200) |
| * width_x64 * height_x32; |
| |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, |
| "%s(%d,%d,%d)=>%d\n", |
| __func__, width, height, |
| is_bit_depth_10, bsize); |
| |
| return bsize; |
| } |
| |
| static int avs3_mmu_page_num(struct AVS3Decoder_s *dec, |
| int pic_width, int pic_height, int is_bit_depth_10) |
| { |
| int picture_size; |
| int cur_mmu_4k_number, max_frame_num; |
| |
| picture_size = |
| compute_losless_comp_body_size(dec, pic_width, pic_height, is_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) { |
| avs3_print(dec, 0, "over max !! 0x%x width %d height %d\n", |
| max_frame_num, pic_width, pic_height); |
| return -1; |
| } |
| return cur_mmu_4k_number; |
| } |
| |
| /* Losless compression header buffer size 32bytes per 128x64 (jt)*/ |
| static int compute_losless_comp_header_size(struct AVS3Decoder_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; |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, |
| "%s(%d,%d)=>%d\n", |
| __func__, width, height, |
| hsize); |
| |
| return hsize; |
| } |
| |
| static void init_buff_spec(struct AVS3Decoder_s *dec, |
| struct BuffInfo_s *buf_spec) |
| { |
| void *mem_start_virt; |
| buf_spec->ipp.buf_start = |
| WORKBUF_ALIGN(buf_spec->start_adr); |
| #ifdef NEW_FRONT_BACK_CODE |
| buf_spec->ipp1.buf_start = |
| WORKBUF_ALIGN(buf_spec->ipp.buf_start + buf_spec->ipp.buf_size); |
| buf_spec->sao_abv.buf_start = |
| WORKBUF_ALIGN(buf_spec->ipp1.buf_start + buf_spec->ipp1.buf_size); |
| #else |
| buf_spec->sao_abv.buf_start = |
| WORKBUF_ALIGN(buf_spec->ipp.buf_start + buf_spec->ipp.buf_size); |
| #endif |
| buf_spec->sao_vb.buf_start = |
| WORKBUF_ALIGN(buf_spec->sao_abv.buf_start + buf_spec->sao_abv.buf_size); |
| buf_spec->short_term_rps.buf_start = |
| WORKBUF_ALIGN(buf_spec->sao_vb.buf_start + buf_spec->sao_vb.buf_size); |
| buf_spec->rcs.buf_start = |
| WORKBUF_ALIGN(buf_spec->short_term_rps.buf_start + buf_spec->short_term_rps.buf_size); |
| buf_spec->sps.buf_start = |
| WORKBUF_ALIGN(buf_spec->rcs.buf_start + buf_spec->rcs.buf_size); |
| buf_spec->pps.buf_start = |
| WORKBUF_ALIGN(buf_spec->sps.buf_start + buf_spec->sps.buf_size); |
| buf_spec->sbac_top.buf_start = |
| WORKBUF_ALIGN(buf_spec->pps.buf_start + buf_spec->pps.buf_size); |
| buf_spec->sao_up.buf_start = |
| WORKBUF_ALIGN(buf_spec->sbac_top.buf_start + buf_spec->sbac_top.buf_size); |
| buf_spec->swap_buf.buf_start = |
| WORKBUF_ALIGN(buf_spec->sao_up.buf_start + buf_spec->sao_up.buf_size); |
| buf_spec->swap_buf2.buf_start = |
| WORKBUF_ALIGN(buf_spec->swap_buf.buf_start + buf_spec->swap_buf.buf_size); |
| buf_spec->scalelut.buf_start = |
| WORKBUF_ALIGN(buf_spec->swap_buf2.buf_start + buf_spec->swap_buf2.buf_size); |
| buf_spec->dblk_para.buf_start = |
| WORKBUF_ALIGN(buf_spec->scalelut.buf_start + buf_spec->scalelut.buf_size); |
| buf_spec->dblk_data.buf_start = |
| WORKBUF_ALIGN(buf_spec->dblk_para.buf_start + buf_spec->dblk_para.buf_size); |
| buf_spec->dblk_data2.buf_start = |
| WORKBUF_ALIGN(buf_spec->dblk_data.buf_start + buf_spec->dblk_data.buf_size); |
| #ifdef AVS3_10B_MMU |
| buf_spec->mmu_vbh.buf_start = |
| WORKBUF_ALIGN(buf_spec->dblk_data2.buf_start + buf_spec->dblk_data2.buf_size); |
| #ifdef AVS3_10B_MMU_DW |
| buf_spec->mmu_vbh_dw.buf_start = |
| WORKBUF_ALIGN(buf_spec->mmu_vbh.buf_start + buf_spec->mmu_vbh.buf_size); |
| buf_spec->mpred_above.buf_start = |
| WORKBUF_ALIGN(buf_spec->mmu_vbh_dw.buf_start + buf_spec->mmu_vbh_dw.buf_size); |
| #else |
| buf_spec->mpred_above.buf_start = |
| WORKBUF_ALIGN(buf_spec->mmu_vbh.buf_start + buf_spec->mmu_vbh.buf_size); |
| #endif |
| #else /* AVS3_10B_MMU */ |
| #ifdef AVS3_10B_MMU_DW |
| buf_spec->mmu_vbh_dw.buf_start = |
| WORKBUF_ALIGN(buf_spec->dblk_data2.buf_start + buf_spec->dblk_data2.buf_size); |
| buf_spec->mpred_above.buf_start = |
| WORKBUF_ALIGN(buf_spec->mmu_vbh_dw.buf_start + buf_spec->mmu_vbh_dw.buf_size); |
| #else |
| buf_spec->mpred_above.buf_start = |
| WORKBUF_ALIGN(buf_spec->dblk_data2.buf_start + buf_spec->dblk_data2.buf_size); |
| #endif |
| #endif /* AVS3_10B_MMU */ |
| #ifdef MV_USE_FIXED_BUF |
| buf_spec->mpred_mv.buf_start = |
| WORKBUF_ALIGN(buf_spec->mpred_above.buf_start + buf_spec->mpred_above.buf_size); |
| buf_spec->rpm.buf_start = |
| WORKBUF_ALIGN(buf_spec->mpred_mv.buf_start + buf_spec->mpred_mv.buf_size); |
| #else |
| buf_spec->rpm.buf_start = |
| WORKBUF_ALIGN(buf_spec->mpred_above.buf_start + buf_spec->mpred_above.buf_size); |
| #endif |
| buf_spec->lmem.buf_start = |
| WORKBUF_ALIGN(buf_spec->rpm.buf_start + buf_spec->rpm.buf_size); |
| buf_spec->end_adr = |
| WORKBUF_ALIGN(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); |
| #ifdef NEW_FRONT_BACK_CODE |
| pr_info("ipp1.buf_start :%x\n", |
| buf_spec->ipp1.buf_start); |
| #endif |
| 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 AVS3_10B_MMU |
| pr_info("mmu_vbh.buf_start :%x\n", |
| buf_spec->mmu_vbh.buf_start); |
| #endif |
| #ifdef AVS3_10B_MMU_DW |
| pr_info("mmu_vbh_dw.buf_start :%x\n", |
| buf_spec->mmu_vbh_dw.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 & AVS3_DBG_SEND_PARAM_WITH_REG) == 0) { |
| pr_info("rpm.buf_start :%x\n", |
| buf_spec->rpm.buf_start); |
| } |
| } |
| } |
| |
| } |
| |
| static void uninit_mmu_buffers(struct AVS3Decoder_s *dec) |
| { |
| #ifdef AVS3_10B_MMU_DW |
| if (dec->dw_mmu_enable && dec->dw_mmu_box) { |
| decoder_mmu_box_free(dec->dw_mmu_box); |
| dec->dw_mmu_box = NULL; |
| } |
| #endif |
| decoder_mmu_box_free(dec->mmu_box); |
| dec->mmu_box = NULL; |
| #ifdef NEW_FB_CODE |
| if (dec->front_back_mode) { |
| if (dec->mmu_box_1) |
| decoder_mmu_box_free(dec->mmu_box_1); |
| dec->mmu_box_1 = NULL; |
| if (dec->dw_mmu_enable && dec->dw_mmu_box_1) { |
| decoder_mmu_box_free(dec->dw_mmu_box_1); |
| dec->dw_mmu_box_1 = NULL; |
| } |
| } |
| if (dec->front_back_mode) { |
| uninit_fb_bufstate(dec); |
| } |
| #endif |
| if (dec->bmmu_box) |
| decoder_bmmu_box_free(dec->bmmu_box); |
| dec->bmmu_box = NULL; |
| } |
| |
| static int config_pic(struct AVS3Decoder_s *dec, |
| struct avs3_frame_s *pic, int32_t lcu_size_log2) |
| { |
| int ret = -1; |
| int i; |
| /* to do: init_pic_w, init_pic_h*/ |
| #if 0 |
| int pic_width = dec->init_pic_w; |
| int pic_height = dec->init_pic_h; |
| #else |
| //simulation |
| int32_t pic_width = dec->avs3_dec.img.width; |
| int32_t pic_height = dec->avs3_dec.img.height; |
| #endif |
| /*struct avs3_decoder *avs3_dec = &dec->avs3_dec; |
| int32_t lcu_size_log2 = avs3_dec->lcu_size_log2;*/ |
| int32_t lcu_size = 1 << dec->avs3_dec.lcu_size_log2; |
| int32_t pic_width_lcu = ( pic_width %lcu_size ) ? pic_width /lcu_size + 1 : pic_width /lcu_size; |
| int32_t pic_height_lcu = ( pic_height %lcu_size ) ? pic_height/lcu_size + 1 : pic_height/lcu_size; |
| int32_t lcu_total =pic_width_lcu*pic_height_lcu; |
| |
| u32 y_adr = 0; |
| int buf_size = 0; |
| int losless_comp_body_size = compute_losless_comp_body_size( |
| dec, pic_width, |
| pic_height, buf_alloc_depth == 10); |
| |
| 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 && ((dw_mode & 0x20) == 0)) { |
| int pic_width_dw = pic_width / |
| get_double_write_ratio(dw_mode); |
| int pic_height_dw = pic_height / |
| get_double_write_ratio(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 (dec->mmu_enable) { |
| pic->header_adr = decoder_bmmu_box_get_phy_addr( |
| dec->bmmu_box, HEADER_BUFFER_IDX(pic->index)); |
| |
| #ifdef AVS3_10B_MMU_DW |
| if (dec->dw_mmu_enable) { |
| pic->dw_header_adr = pic->header_adr |
| + get_compress_header_size(dec); |
| } |
| #endif |
| } |
| |
| i = pic->index; |
| |
| /*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) { |
| avs3_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; |
| if (!vdec_secure(hw_to_vdec(dec))) |
| codec_mm_memset(y_adr, 0, buf_size); |
| } else { |
| avs3_print(dec, 0, |
| "decoder_bmmu_box_alloc_buf_phy idx %d size %d return null\n", |
| VF_BUFFER_IDX(i), |
| buf_size |
| ); |
| return -1; |
| } |
| } |
| |
| /*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; |
| pic->mc_canvas_y = pic->index; |
| pic->mc_canvas_u_v = pic->index; |
| if (dw_mode) { |
| pic->dw_y_adr = y_adr; |
| pic->dw_u_v_adr = pic->dw_y_adr + |
| ((mc_buffer_size_u_v_h << 16) << 1); |
| pic->mc_y_adr = pic->dw_y_adr; |
| pic->mc_u_v_adr = pic->dw_u_v_adr; |
| } |
| #ifdef MV_USE_FIXED_BUF |
| pic->mpred_mv_wr_start_addr = |
| dec->work_space_buf->mpred_mv.buf_start + |
| pic->index * (dec->work_space_buf->mpred_mv.buf_size / FRAME_BUFFERS); |
| if (pic->mpred_mv_wr_start_addr > |
| (dec->work_space_buf->mpred_mv.buf_start |
| + dec->work_space_buf->mpred_mv.buf_size)) { |
| avs3_print(dec, 0, "err: fixed mv buf out of size, 0x0%x\n", |
| pic->mpred_mv_wr_start_addr); |
| pic->mpred_mv_wr_start_addr = |
| dec->work_space_buf->mpred_mv.buf_start; |
| } |
| #endif |
| if (debug) { |
| avs3_print_cont(dec, AVS3_DBG_BUFMGR, |
| "%s index %d, head_size 0x%08x, MMU header_adr 0x%08x, dw_header_adr 0x%08x; ", |
| __func__, pic->index, get_compress_header_size(dec), |
| pic->header_adr, pic->dw_header_adr); |
| |
| avs3_print_cont(dec, AVS3_DBG_BUFMGR, |
| "dw_y_adr 0x%08x, dw_u_v_adr 0x%08x, ", |
| pic->dw_y_adr, |
| pic->dw_u_v_adr); |
| |
| avs3_print_cont(dec, AVS3_DBG_BUFMGR, |
| "comp_body_size %x comp_buf_size %x ;", |
| pic->comp_body_size, |
| pic->buf_size); |
| avs3_print_cont(dec, AVS3_DBG_BUFMGR, |
| "mpred_mv_wr_start_adr %d\n", |
| pic->mpred_mv_wr_start_addr); |
| avs3_print_flush(dec); |
| } |
| |
| ret = 0; |
| return ret; |
| } |
| |
| static void init_pic_list(struct AVS3Decoder_s *dec, |
| int32_t lcu_size_log2) |
| { |
| int i; |
| struct avs3_decoder *avs3_dec = &dec->avs3_dec; |
| struct avs3_frame_s *pic; |
| #ifdef AVS3_10B_MMU |
| if (dec->mmu_enable) { |
| for (i = 0; i < avs3_dec->max_pb_size; i++) { |
| unsigned long buf_addr; |
| u32 header_size = get_compress_header_size(dec); |
| #ifdef AVS3_10B_MMU_DW |
| if (dec->dw_mmu_enable) |
| header_size <<= 1; |
| #endif |
| if (decoder_bmmu_box_alloc_buf_phy |
| (dec->bmmu_box, |
| HEADER_BUFFER_IDX(i), header_size, |
| DRIVER_HEADER_NAME, |
| &buf_addr) < 0) { |
| avs3_print(dec, 0, |
| "%s malloc compress header failed %d\n", |
| DRIVER_HEADER_NAME, i); |
| dec->fatal_error |= DECODER_FATAL_ERROR_NO_MEM; |
| return; |
| } |
| if (!vdec_secure(hw_to_vdec(dec))) |
| codec_mm_memset(buf_addr, 0, header_size); |
| } |
| } |
| #endif |
| dec->frame_height = avs3_dec->img.height; |
| dec->frame_width = avs3_dec->img.width; |
| |
| for (i = 0; i < avs3_dec->max_pb_size; i++) { |
| pic = &avs3_dec->pic_pool[i].buf_cfg; |
| pic->index = i; |
| pic->BUF_index = -1; |
| //pic->mv_buf_index = -1; |
| if (config_pic(dec, pic, lcu_size_log2) < 0) { |
| //if (debug) |
| avs3_print(dec, 0, |
| "Config_pic %d fail\n", |
| pic->index); |
| pic->index = -1; |
| break; |
| } |
| pic->width = avs3_dec->img.width; |
| pic->height = avs3_dec->img.height; |
| } |
| for (; i < avs3_dec->max_pb_size; i++) { |
| pic = &avs3_dec->pic_pool[i].buf_cfg; |
| pic->index = -1; |
| pic->BUF_index = -1; |
| //pic->mv_buf_index = -1; |
| } |
| avs3_print(dec, AVS3_DBG_BUFMGR, |
| "%s ok, max_pb_size = %d\n", |
| __func__, avs3_dec->max_pb_size); |
| dec->pic_list_wait_alloc_done_flag = BUFFER_ALLOCATE_DONE; |
| } |
| |
| static void init_pic_list_hw(struct AVS3Decoder_s *dec) |
| { |
| int i; |
| struct avs3_decoder *avs3_dec = &dec->avs3_dec; |
| struct avs3_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 < avs3_dec->max_pb_size; i++) { |
| pic = &avs3_dec->pic_pool[i].buf_cfg; |
| if (pic->index < 0) |
| break; |
| #ifdef AVS3_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 AVS3_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 |
| } |
| } |
| |
| #ifdef DEBUG_CMD |
| #if 0 |
| static void d_fill_zero(struct AVS3Decoder_s *hw, unsigned int phyadr, int size) |
| { |
| WRITE_VREG(HEVC_DBG_LOG_ADR, phyadr); |
| WRITE_VREG(DEBUG_REG1, |
| 0x20000000 | size); |
| debug_cmd_wait_count = 0; |
| debug_cmd_wait_type = 1; |
| while ((READ_VREG(DEBUG_REG1) & 0x1) == 0 |
| && debug_cmd_wait_count < 0x7fffffff) { |
| debug_cmd_wait_count++; |
| } |
| |
| WRITE_VREG(DEBUG_REG1, 0); |
| debug_cmd_wait_type = 0; |
| } |
| #endif |
| #if 0 |
| static void d_dump(struct AVS3Decoder_s *hw, unsigned int phyadr, int size, |
| struct file *fp, loff_t *wr_off) |
| { |
| |
| int jj; |
| unsigned char *data = (unsigned char *) |
| (hw->ucode_log_addr); |
| WRITE_VREG(HEVC_DBG_LOG_ADR, hw->ucode_log_phy_addr); |
| |
| WRITE_VREG(HEVC_D_ADR, phyadr); |
| WRITE_VREG(DEBUG_REG1, |
| 0x10000000 | size); |
| |
| debug_cmd_wait_count = 0; |
| debug_cmd_wait_type = 3; |
| while ((READ_VREG(DEBUG_REG1) & 0x1) == 0 |
| && debug_cmd_wait_count < 0x7fffffff) { |
| debug_cmd_wait_count++; |
| } |
| |
| if (fp) { |
| vfs_write(fp, data, |
| size, wr_off); |
| |
| } else { |
| for (jj = 0; jj < size; jj++) { |
| if ((jj & 0xf) == 0) |
| avs3_print(hw, 0, |
| "%06x:", jj); |
| avs3_print_cont(hw, 0, |
| "%02x ", data[jj]); |
| if (((jj + 1) & 0xf) == 0) |
| avs3_print_cont(hw, 0, |
| "\n"); |
| } |
| avs3_print(hw, 0, "\n"); |
| } |
| |
| WRITE_VREG(DEBUG_REG1, 0); |
| debug_cmd_wait_type = 0; |
| |
| } |
| |
| static void mv_buffer_fill_zero(struct AVS3Decoder_s *hw, struct PIC_BUFFER_CONFIG_s *pic_config) |
| { |
| pr_info("fill dummy data pic index %d colocate addresses %x size %x\n", |
| pic_config->index, pic_config->mpred_mv_wr_start_addr, |
| hw->m_mv_BUF[pic_config->mv_buf_index].size); |
| d_fill_zero(hw, pic_config->mpred_mv_wr_start_addr, |
| hw->m_mv_BUF[pic_config->mv_buf_index].size); |
| } |
| |
| static void dump_mv_buffer(struct AVS3Decoder_s *hw, struct PIC_BUFFER_CONFIG_s *pic_config) |
| { |
| |
| unsigned int adr, size; |
| unsigned int adr_end = pic_config->mpred_mv_wr_start_addr + |
| hw->m_mv_BUF[pic_config->mv_buf_index].size; |
| mm_segment_t old_fs; |
| loff_t off = 0; |
| int mode = O_CREAT | O_WRONLY | O_TRUNC; |
| char file[64]; |
| struct file *fp; |
| sprintf(&file[0], "/data/tmp/colocate%d", hw->frame_count-1); |
| fp = filp_open(file, mode, 0666); |
| old_fs = get_fs(); |
| set_fs(KERNEL_DS); |
| for (adr = pic_config->mpred_mv_wr_start_addr; |
| adr < adr_end; |
| adr += UCODE_LOG_BUF_SIZE) { |
| size = UCODE_LOG_BUF_SIZE; |
| if (size > (adr_end - adr)) |
| size = adr_end - adr; |
| pr_info("dump pic index %d colocate addresses %x size %x\n", |
| pic_config->index, adr, size); |
| d_dump(hw, adr, size, fp, &off); |
| } |
| set_fs(old_fs); |
| vfs_fsync(fp, 0); |
| |
| filp_close(fp, current->files); |
| } |
| #endif |
| #endif |
| |
| static int config_mc_buffer(struct AVS3Decoder_s *dec) |
| { |
| int32_t i; |
| struct avs3_decoder *avs3_dec = &dec->avs3_dec; |
| //avs3_frame_t *cur_pic = avs3_dec->cur_pic; |
| avs3_frame_t *pic; |
| //uint32_t rdata32; |
| //uint32_t rdata32_2; |
| //if (avs3_dec->img.type == I_IMG) |
| // return 0; |
| avs3_print(dec, AVS3_DBG_BUFMGR_MORE, |
| "Entered config_mc_buffer....\n"); |
| if (avs3_dec->f_bg != NULL) { |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, |
| "config_mc_buffer for background (canvas_y %d, canvas_u_v %d)\n", |
| avs3_dec->f_bg->mc_canvas_y, avs3_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, |
| (avs3_dec->f_bg->mc_canvas_u_v<<16)|(avs3_dec->f_bg->mc_canvas_u_v<<8)|avs3_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, |
| (avs3_dec->f_bg->mc_canvas_u_v<<16)|(avs3_dec->f_bg->mc_canvas_u_v<<8)|avs3_dec->f_bg->mc_canvas_y); |
| } |
| if (avs3_dec->slice_type == SLICE_I) |
| return 0; |
| if (avs3_dec->slice_type == SLICE_P || avs3_dec->slice_type == SLICE_B) { |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, |
| "config_mc_buffer for REF_0, img type %d\n", avs3_dec->slice_type); |
| WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, (0 << 8) | (0<<1) | 1); |
| for (i = 0; i < avs3_dec->ctx.dpm.num_refp[REFP_0]; i++) { |
| pic = &avs3_dec->ctx.refp[i][REFP_0].pic->buf_cfg; |
| 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) { |
| avs3_dec->ctx.pic->buf_cfg.error_mark = 1; |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, "%s:L0 refid %d pic error\n", __func__, i); |
| } |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, |
| "L0 refid %x mc_canvas_u_v %x mc_canvas_y %x\n", i, pic->mc_canvas_u_v, pic->mc_canvas_y); |
| } |
| } |
| if (avs3_dec->slice_type == SLICE_B) { |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, |
| "config_mc_buffer for REF_1\n"); |
| |
| WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, (16 << 8) | (0<<1) | 1); |
| for (i = 0; i < avs3_dec->ctx.dpm.num_refp[REFP_1]; i++) { |
| pic = &avs3_dec->ctx.refp[i][REFP_1].pic->buf_cfg; |
| 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) { |
| avs3_dec->ctx.pic->buf_cfg.error_mark = 1; |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, "%s:L1 refid %d pic error\n", __func__, i); |
| } |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, |
| "L1 refid %x mc_canvas_u_v %x mc_canvas_y %x\n", i, pic->mc_canvas_u_v, pic->mc_canvas_y); |
| } |
| } |
| 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 & AVS3_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 & AVS3_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 & AVS3_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 & AVS3_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 & AVS3_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 & AVS3_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 & AVS3_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 & AVS3_DBG_CACHE) |
| pr_info("MCRCC_BYP_RATE : %d\n", hitrate); |
| } else if (debug & AVS3_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 & AVS3_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 & AVS3_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 & AVS3_DBG_CACHE) |
| pr_info("DECOMP_HCACHE_HIT_RATE : %d\n", hitrate); |
| } else { |
| if (debug & AVS3_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 & AVS3_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 & AVS3_DBG_CACHE) |
| pr_info("DECOMP_DCACHE_HIT_RATE : %d\n", hitrate); |
| } else if (debug & AVS3_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 & AVS3_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 & AVS3_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 & AVS3_DBG_CACHE) |
| pr_info("DECOMP_COMP_RATIO : %d\n", comprate); |
| } else if (debug & AVS3_DBG_CACHE) { |
| pr_info("DECOMP_COMP_RATIO : na\n"); |
| } |
| return; |
| } |
| #endif |
| |
| static void config_mcrcc_axi_hw(struct AVS3Decoder_s *dec) |
| { |
| struct avs3_decoder *avs3_dec = &dec->avs3_dec; |
| uint32_t rdata32; |
| uint32_t rdata32_2; |
| |
| WRITE_VREG(HEVCD_MCRCC_CTL1, 0x2); // reset mcrcc |
| if (avs3_dec->slice_type == SLICE_I) { |
| WRITE_VREG(HEVCD_MCRCC_CTL1, 0x0); // remove reset -- disables clock |
| return; |
| } |
| |
| #if 0 |
| mcrcc_get_hitrate(); |
| decomp_get_hitrate(); |
| decomp_get_comprate(); |
| #endif |
| if ((avs3_dec->slice_type == SLICE_B) || (avs3_dec->slice_type == SLICE_P)) { |
| // 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); |
| } |
| |
| WRITE_VREG(HEVCD_MCRCC_CTL1, 0xff0); // enable mcrcc progressive-mode |
| return; |
| } |
| |
| static void config_mpred_hw(struct AVS3Decoder_s *dec) |
| { |
| struct avs3_decoder *avs3_dec = &dec->avs3_dec; |
| int32_t i; |
| uint32_t data32; |
| avs3_frame_t *cur_pic = avs3_dec->cur_pic; |
| avs3_frame_t *col_pic; |
| //COM_PIC *colPic; |
| |
| //int32_t AMVP_MAX_NUM_CANDS_MEM=3; |
| //int32_t AMVP_MAX_NUM_CANDS=2; |
| //int32_t NUM_CHROMA_MODE=5; |
| //int32_t DM_CHROMA_IDX=36; |
| int32_t above_ptr_ctrl =0; |
| //int32_t buffer_linear =1; |
| //int32_t cu_size_log2 =3; |
| int32_t mpred_mv_rd_start_addr ; |
| //int32_t mpred_curr_lcu_x; |
| //int32_t mpred_curr_lcu_y; |
| //int32_t mpred_above_buf_start ; |
| //int32_t mpred_mv_rd_ptr ; |
| //int32_t mpred_mv_rd_ptr_p1 ; |
| int32_t mpred_mv_rd_end_addr; |
| int32_t MV_MEM_UNIT_l; |
| //int32_t mpred_mv_wr_ptr ; |
| |
| int32_t above_en; |
| int32_t mv_wr_en; |
| int32_t mv_rd_en; |
| int32_t col_isIntra; |
| int32_t col_ptr; |
| |
| if (avs3_dec->slice_type == SLICE_P) { |
| col_pic = &avs3_dec->ctx.refp[0][REFP_0].pic->buf_cfg; |
| } |
| else if (avs3_dec->slice_type == SLICE_B) { |
| col_pic = &avs3_dec->ctx.refp[0][REFP_1].pic->buf_cfg; |
| } |
| else { |
| col_pic = cur_pic; |
| } |
| |
| //if (dec->slice_type!=2) |
| if (avs3_dec->slice_type != SLICE_I) |
| { |
| above_en=1; |
| mv_wr_en=1; |
| if (col_pic->slice_type != SLICE_I) |
| mv_rd_en=1; |
| else |
| mv_rd_en=0; |
| 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_l=get_mv_mem_unit(avs3_dec->lcu_size_log2); |
| |
| mpred_mv_rd_end_addr=mpred_mv_rd_start_addr + ((avs3_dec->lcu_x_num*avs3_dec->lcu_y_num)*MV_MEM_UNIT_l); |
| |
| //mpred_above_buf_start = buf_spec->mpred_above.buf_start; |
| |
| avs3_print(dec, AVS3_DBG_BUFMGR_MORE, |
| "cur pic index %d slicetype %d col pic index %d slicetype %d\n", |
| cur_pic->index, cur_pic->slice_type, |
| col_pic->index, col_pic->slice_type); |
| |
| 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); |
| avs3_print(dec, AVS3_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 = |
| ((avs3_dec->bk_img_is_top_field) << 13) | |
| ((avs3_dec->hd.background_picture_enable & 1) << 12) | |
| ((avs3_dec->hd.curr_RPS.num_of_ref & 7) << 8) | |
| ((avs3_dec->hd.b_pmvr_enabled & 1) << 6) | |
| ((avs3_dec->img.is_top_field & 1) << 5) | |
| ((avs3_dec->img.is_field_sequence & 1) << 4) | |
| ((avs3_dec->img.typeb & 7) << 1) | |
| (avs3_dec->hd.background_reference_enable & 0x1); |
| printk("HEVC_MPRED_CTRL9 <= 0x%x(num of ref %d)\n", data32, avs3_dec->hd.curr_RPS.num_of_ref); |
| WRITE_VREG(HEVC_MPRED_CTRL9, data32); |
| */ |
| #if 1 |
| /* |
| data32 = ((dec->lcu_x_num - dec->tile_width_lcu)*MV_MEM_UNIT); |
| WRITE_VREG(HEVC_MPRED_MV_WR_ROW_JUMP,data32); |
| WRITE_VREG(HEVC_MPRED_MV_RD_ROW_JUMP,data32); |
| */ |
| data32 = READ_VREG(HEVC_MPRED_CTRL0); |
| data32 &= (~(0x3 | (0xf << 8) | (0xf << 16))); |
| data32 = ( |
| avs3_dec->slice_type | |
| /*dec->new_pic<<2 | |
| dec->new_tile<<3| |
| dec->isNextSliceSegment<<4| |
| dec->TMVPFlag<<5| |
| dec->LDCFlag<<6| |
| dec->ColFromL0Flag<<7| |
| */ |
| above_ptr_ctrl<<8 | |
| above_en<<9| |
| mv_wr_en<<10| |
| mv_rd_en<<11| |
| avs3_dec->lcu_size_log2<<16 |
| /*|cu_size_log2<<20*/ |
| ); |
| WRITE_VREG(HEVC_MPRED_CTRL0,data32); |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, |
| "P_HEVC_MPRED_CTRL0=0x%x\n", |
| READ_VREG(HEVC_MPRED_CTRL0)); |
| |
| data32 = READ_VREG(HEVC_MPRED_CTRL1); |
| data32 &= (~0xf); |
| data32 |= avs3_dec->ctx.info.sqh.num_of_hmvp_cand; |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, |
| "write P_HEVC_MPRED_CTRL1=0x%x, avs3_dec->ctx.info.sqh.num_of_hmvp_cand=%d\n", |
| data32, avs3_dec->ctx.info.sqh.num_of_hmvp_cand); |
| WRITE_VREG(HEVC_MPRED_CTRL1,data32); |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, |
| "P_HEVC_MPRED_CTRL1=0x%x\n", |
| READ_VREG(HEVC_MPRED_CTRL1)); |
| |
| data32 = ( |
| avs3_dec->img.width| |
| avs3_dec->img.height<<16 |
| ); |
| WRITE_VREG(HEVC_MPRED_PIC_SIZE,data32); |
| |
| data32 = ( |
| (avs3_dec->lcu_x_num-1) | |
| (avs3_dec->lcu_y_num-1)<<16 |
| ); |
| WRITE_VREG(HEVC_MPRED_PIC_SIZE_LCU,data32); |
| |
| /*data32 = ( |
| dec->tile_start_lcu_x | |
| dec->tile_start_lcu_y<<16 |
| ); |
| WRITE_VREG(HEVC_MPRED_TILE_START,data32); |
| data32 = ( |
| dec->tile_width_lcu | |
| dec->tile_height_lcu<<16 |
| ); |
| WRITE_VREG(HEVC_MPRED_TILE_SIZE_LCU,data32); |
| */ |
| data32 = ( |
| avs3_dec->ctx.dpm.num_refp[REFP_0] | |
| avs3_dec->ctx.dpm.num_refp[REFP_1]<<8| |
| 0 |
| //col_RefNum_L0<<16| |
| //col_RefNum_L1<<24 |
| ); |
| WRITE_VREG(HEVC_MPRED_REF_NUM,data32); |
| |
| data32=0; |
| for (i=0;i<avs3_dec->ctx.dpm.num_refp[REFP_0];i++)data32=data32|(1<<i); |
| WRITE_VREG(HEVC_MPRED_REF_EN_L0,data32); |
| |
| data32=0; |
| for (i=0;i<avs3_dec->ctx.dpm.num_refp[REFP_1];i++)data32=data32|(1<<i); |
| WRITE_VREG(HEVC_MPRED_REF_EN_L1,data32); |
| #endif |
| |
| WRITE_VREG(HEVC_MPRED_CUR_POC, avs3_dec->ctx.ptr & 0xffff); |
| if (avs3_dec->slice_type == SLICE_P) { |
| col_ptr = avs3_dec->ctx.refp[0][REFP_0].ptr; |
| //colPic = avs3_dec->ctx.refp[0][REFP_0].pic; |
| } |
| else if (avs3_dec->slice_type == SLICE_B) { |
| col_ptr = avs3_dec->ctx.refp[0][REFP_1].ptr; |
| //colPic = avs3_dec->ctx.refp[0][REFP_0].pic; |
| } |
| else { |
| col_ptr = avs3_dec->ctx.pic->ptr; |
| //colPic = avs3_dec->ctx.pic; |
| } |
| WRITE_VREG(HEVC_MPRED_COL_POC, col_ptr & 0xffff); |
| //below MPRED Ref_POC_xx_Lx registers must follow Ref_POC_xx_L0 -> Ref_POC_xx_L1 in pair write order!!! |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, |
| "P_HEVC_MPRED_CUR_POC=0x%x, P_HEVC_MPRED_COL_POC=0x%x\n", |
| READ_VREG(HEVC_MPRED_CUR_POC), READ_VREG(HEVC_MPRED_COL_POC)); |
| |
| for (i = 0; i < MAX_NUM_REF_PICS; i++) { |
| data32 = 0; |
| if (i < cur_pic->list0_num_refp || i < col_pic->list0_num_refp) { |
| if (i < cur_pic->list0_num_refp) { |
| data32 |= cur_pic->list0_ptr[i] & 0xffff; |
| } |
| if (i < col_pic->list0_num_refp) { |
| data32 |= ((col_pic->list0_ptr[i] & 0xffff) << 16); |
| } |
| } |
| WRITE_VREG(HEVC_MPRED_L0_REF_POC_ADR[i], data32); |
| } |
| if (debug & AVS3_DBG_BUFMGR_DETAIL) { |
| for (i = 0; i < MAX_NUM_REF_PICS; i++) { |
| if (i < cur_pic->list0_num_refp || i < col_pic->list0_num_refp) { |
| if (i < cur_pic->list0_num_refp) { |
| avs3_print_cont(dec, AVS3_DBG_BUFMGR_DETAIL, |
| "[%d] ", cur_pic->list0_ptr[i]); |
| } |
| if (i < col_pic->list0_num_refp) { |
| avs3_print_cont(dec, AVS3_DBG_BUFMGR_DETAIL, |
| "<%d> ", col_pic->list0_ptr[i]); |
| } |
| } |
| if (i < cur_pic->list0_num_refp || i < col_pic->list0_num_refp) { |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, |
| "P_HEVC_MPRED_L0_REF=0x%x (readback 0x%x)\n", i, |
| data32, READ_VREG(HEVC_MPRED_L0_REF_POC_ADR[i])); |
| } |
| } |
| } |
| for (i = 0; i < avs3_dec->ctx.dpm.num_refp[REFP_1]; i++) { |
| WRITE_VREG(HEVC_MPRED_L1_REF_POC_ADR[i], avs3_dec->ctx.refp[i][REFP_1].ptr & 0xffff); |
| } |
| if (debug & AVS3_DBG_BUFMGR_DETAIL) { |
| for (i = 0; i < avs3_dec->ctx.dpm.num_refp[REFP_1]; i++) { |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, |
| "P_HEVC_MPRED_L1_REF%02d_POC=0x%x (readback 0x%x)\n", i, avs3_dec->ctx.refp[i][REFP_1].ptr & 0xffff, READ_VREG(HEVC_MPRED_L1_REF_POC_ADR[i])); |
| } |
| } |
| |
| #if 0 |
| if (dec->new_pic) |
| { |
| WRITE_VREG(HEVC_MPRED_ABV_START_ADDR,mpred_above_buf_start); |
| WRITE_VREG(HEVC_MPRED_MV_WPTR,mpred_mv_wr_ptr); |
| //WRITE_VREG(HEVC_MPRED_MV_RPTR,mpred_mv_rd_ptr); |
| WRITE_VREG(HEVC_MPRED_MV_RPTR,mpred_mv_rd_start_addr); |
| } |
| else if (!dec->isNextSliceSegment) |
| { |
| //WRITE_VREG(HEVC_MPRED_MV_RPTR,mpred_mv_rd_ptr_p1); |
| WRITE_VREG(HEVC_MPRED_MV_RPTR,mpred_mv_rd_ptr); |
| } |
| #endif |
| WRITE_VREG(HEVC_MPRED_MV_RD_END_ADDR,mpred_mv_rd_end_addr); |
| } |
| |
| static void config_dblk_hw(struct AVS3Decoder_s *dec) |
| { |
| /* |
| * Picture level de-block parameter configuration here |
| */ |
| struct avs3_decoder *avs3_dec = &dec->avs3_dec; |
| union param_u *rpm_param = &avs3_dec->param; |
| uint32_t data32; |
| DEC_CTX * ctx = &avs3_dec->ctx; |
| int32_t alpha_c_offset = rpm_param->p.pic_header_alpha_c_offset; |
| int32_t beta_offset = rpm_param->p.pic_header_beta_offset; |
| |
| alpha_c_offset = (alpha_c_offset >=16) ? 15 : ((alpha_c_offset < -16) ? -16 : alpha_c_offset); |
| beta_offset = (beta_offset >=16) ? 15 : ((beta_offset < -16) ? -16 : beta_offset); |
| |
| data32 = READ_VREG(HEVC_DBLK_CFG1); |
| data32 = (((data32>>20)&0xfff)<<20) | |
| (((ctx->info.bit_depth_internal == 10) ? 0xa:0x0)<<16) | // [16 +: 4]: {luma_bd[1:0],chroma_bd[1:0]} |
| (((data32>>2)&0x3fff)<<2) | |
| (((ctx->info.log2_max_cuwh == 6) ? 0:(ctx->info.log2_max_cuwh == 5) ? 1:(ctx->info.log2_max_cuwh == 4) ? 2:3)<<0);// [ 0 +: 2]: lcu_size |
| WRITE_VREG(HEVC_DBLK_CFG1, data32); |
| |
| data32 = (avs3_dec->img.height<<16) | avs3_dec->img.width; |
| WRITE_VREG(HEVC_DBLK_CFG2, data32); |
| |
| data32 = ((rpm_param->p.sqh_cross_patch_loop_filter & 0x1)<<27) |// [27 +: 1]: cross_slice_loopfilter_enable_flag |
| ((rpm_param->p.pic_header_loop_filter_disable_flag & 0x1)<<26) | // [26 +: 1]: loop_filter_disable |
| ((alpha_c_offset&0x1f) <<17) | // [17 +: 5]: alpha_c_offset (-8~8) |
| ((beta_offset&0x1f) <<12) | // [12 +: 5]: beta_offset (-8~8) |
| ((rpm_param->p.pic_header_chroma_quant_param_delta_cb&0x3f)<<6) | // [ 6 +: 6]: chroma_quant_param_delta_u (-16~16) |
| ((rpm_param->p.pic_header_chroma_quant_param_delta_cr&0x3f)<<0); // [ 0 +: 6]: chroma_quant_param_delta_v (-16~16) |
| WRITE_VREG(HEVC_DBLK_CFG9, data32); |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, |
| "[c] cfgDBLK: crossslice(%d),lfdisable(%d),bitDepth(%d,%d),log2_lcuSize(%d)\n", |
| rpm_param->p.sqh_cross_patch_loop_filter,rpm_param->p.pic_header_loop_filter_disable_flag, |
| ctx->info.bit_depth_input,ctx->info.bit_depth_internal,ctx->info.log2_max_cuwh); |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, |
| "[c] cfgDBLK: alphaCOffset(%d crop to %d),betaOffset(%d crop to %d),quantDeltaCb(%d),quantDeltaCr(%d)\n", |
| rpm_param->p.pic_header_alpha_c_offset, alpha_c_offset,rpm_param->p.pic_header_beta_offset, beta_offset, |
| rpm_param->p.pic_header_chroma_quant_param_delta_cb,rpm_param->p.pic_header_chroma_quant_param_delta_cr); |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, |
| "[c] cfgDBLK: .done.\n"); |
| |
| } |
| |
| static void config_dw(struct AVS3Decoder_s *dec, struct avs3_frame_s *pic, |
| u32 mc_buffer_size_u_v_h) |
| { |
| |
| int dw_mode = get_double_write_mode(dec); |
| uint32_t data32; |
| if ((dw_mode & 0x10) == 0) { |
| WRITE_VREG(HEVC_SAO_CTRL26, 0); |
| |
| data32 = READ_VREG(HEVC_SAO_CTRL5); |
| data32 &= (~(0xff << 16)); |
| if (((dw_mode & 0xf) == 8) || |
| ((dw_mode & 0xf) == 9)) { |
| data32 |= (0xff << 16); |
| WRITE_VREG(HEVC_SAO_CTRL5, data32); |
| WRITE_VREG(HEVC_SAO_CTRL26, 0xf); |
| } else { |
| if ((dw_mode & 0xf) == 2 || |
| (dw_mode & 0xf) == 3) |
| data32 |= (0xff<<16); |
| else if ((dw_mode & 0xf) == 4 || |
| (dw_mode & 0xf) == 5) |
| data32 |= (0x33<<16); |
| |
| /*if (dec->mem_saving_mode == 1) |
| data32 |= (1 << 9); |
| else*/ |
| data32 &= ~(1 << 9); |
| /*if (workaround_enable & 1) |
| data32 |= (1 << 7);*/ |
| WRITE_VREG(HEVC_SAO_CTRL5, data32); |
| } |
| } |
| |
| /* m8baby test1902 */ |
| data32 = READ_VREG(HEVC_SAO_CTRL1); |
| data32 &= (~0x3000); |
| /* [13:12] axi_aformat, 0-Linear, 1-32x32, 2-64x32 */ |
| data32 |= (MEM_MAP_MODE << 12); |
| data32 &= (~0xff0); |
| #ifdef AVS3_10B_MMU_DW |
| if (dec->dw_mmu_enable == 0) |
| data32 |= ((dec->endian >> 8) & 0xfff); //endian: ((0x880 << 8) | 0x8) or ((0xff0 << 8) | 0xf) |
| #else |
| data32 |= ((dec->endian >> 8) & 0xfff); /* data32 |= 0x670; Big-Endian per 64-bit */ |
| #endif |
| |
| data32 &= (~0x3); /*[1]:dw_disable [0]:cm_disable*/ |
| if (dw_mode == 0) |
| data32 |= 0x2; /*disable double write*/ |
| else if (dw_mode & 0x10) |
| data32 |= 0x1; /*disable cm*/ |
| |
| data32 &= (~(3 << 14)); |
| data32 |= (2 << 14); |
| /* |
| * [31:24] ar_fifo1_axi_thred |
| * [23:16] ar_fifo0_axi_thred |
| * [15:14] axi_linealign, 0-16bytes, 1-32bytes, 2-64bytes |
| * [13:12] axi_aformat, 0-Linear, 1-32x32, 2-64x32 |
| * [11:08] axi_lendian_C |
| * [07:04] axi_lendian_Y |
| * [3] reserved |
| * [2] clk_forceon |
| * [1] dw_disable:disable double write output |
| * [0] cm_disable:disable compress output |
| */ |
| WRITE_VREG(HEVC_SAO_CTRL1, data32); |
| |
| data32 = READ_VREG(HEVC_DBLK_CFGB); |
| data32 &= (~0x300); /*[8]:first write enable (compress) |
| [9]:double write enable (uncompress)*/ |
| if (dw_mode == 0) |
| data32 |= (0x1 << 8); /*enable first write*/ |
| else if (dw_mode == 0x10) |
| data32 |= (0x1 << 9); /*double write only*/ |
| else |
| data32 |= ((0x1 << 8) | (0x1 << 9)); |
| WRITE_VREG(HEVC_DBLK_CFGB, data32); |
| |
| if (dw_mode & 0x10) { |
| /* [23:22] dw_v1_ctrl |
| *[21:20] dw_v0_ctrl |
| *[19:18] dw_h1_ctrl |
| *[17:16] dw_h0_ctrl |
| */ |
| data32 = READ_VREG(HEVC_SAO_CTRL5); |
| /*set them all 0 for H265_NV21 (no down-scale)*/ |
| data32 &= ~(0xff << 16); |
| WRITE_VREG(HEVC_SAO_CTRL5, data32); |
| } |
| |
| #ifdef LOSLESS_COMPRESS_MODE |
| /*SUPPORT_10BIT*/ |
| |
| data32 = pic->mc_y_adr; |
| if (dw_mode && ((dw_mode & 0x20) == 0)) { |
| WRITE_VREG(HEVC_SAO_Y_START_ADDR, pic->dw_y_adr); |
| WRITE_VREG(HEVC_SAO_C_START_ADDR, pic->dw_u_v_adr); |
| WRITE_VREG(HEVC_SAO_Y_WPTR, pic->dw_y_adr); |
| WRITE_VREG(HEVC_SAO_C_WPTR, pic->dw_u_v_adr); |
| } else { |
| WRITE_VREG(HEVC_SAO_Y_START_ADDR, 0xffffffff); |
| WRITE_VREG(HEVC_SAO_C_START_ADDR, 0xffffffff); |
| } |
| if ((dw_mode & 0x10) == 0) |
| WRITE_VREG(HEVC_CM_BODY_START_ADDR, data32); |
| |
| if (dec->mmu_enable) |
| WRITE_VREG(HEVC_CM_HEADER_START_ADDR, pic->header_adr); |
| #ifdef AVS3_10B_MMU_DW |
| if (dec->dw_mmu_enable) { |
| WRITE_VREG(HEVC_SAO_Y_START_ADDR, 0); |
| WRITE_VREG(HEVC_SAO_C_START_ADDR, 0); |
| WRITE_VREG(HEVC_CM_HEADER_START_ADDR2, pic->dw_header_adr); |
| } |
| #endif |
| #else |
| WRITE_VREG(HEVC_SAO_Y_START_ADDR, pic->mc_y_adr); |
| WRITE_VREG(HEVC_SAO_C_START_ADDR, pic->mc_u_v_adr); |
| WRITE_VREG(HEVC_SAO_Y_WPTR, pic->mc_y_adr); |
| WRITE_VREG(HEVC_SAO_C_WPTR, pic->mc_u_v_adr); |
| #endif |
| data32 = (mc_buffer_size_u_v_h << 16) << 1; |
| WRITE_VREG(HEVC_SAO_Y_LENGTH, data32); |
| |
| data32 = (mc_buffer_size_u_v_h << 16); |
| WRITE_VREG(HEVC_SAO_C_LENGTH, data32); |
| |
| } |
| |
| static void config_sao_hw(struct AVS3Decoder_s *dec) |
| { |
| struct avs3_decoder *avs3_dec = &dec->avs3_dec; |
| avs3_frame_t *pic = avs3_dec->cur_pic; |
| //union param_u* params = &avs3_dec->param; |
| uint32_t data32; |
| int32_t pic_width = avs3_dec->img.width; |
| int32_t pic_height = avs3_dec->img.height; |
| int32_t lcu_size_log2 = avs3_dec->lcu_size_log2; |
| int32_t lcu_size = 1<<lcu_size_log2; |
| int32_t pic_width_lcu = ( pic_width % lcu_size ) ? pic_width /lcu_size + 1 : pic_width /lcu_size; |
| int32_t pic_height_lcu = ( pic_height % lcu_size ) ? pic_height/lcu_size + 1 : pic_height/lcu_size; |
| int32_t lcu_total = pic_width_lcu*pic_height_lcu; |
| int32_t mc_buffer_size_u_v = lcu_total*lcu_size*lcu_size/2; |
| int32_t mc_buffer_size_u_v_h = (mc_buffer_size_u_v + 0xffff)>>16; //64k alignment |
| |
| config_dw(dec, pic, mc_buffer_size_u_v_h); |
| data32 = READ_VREG(HEVC_SAO_CTRL0); |
| data32 &= (~0xf); |
| data32 |= avs3_dec->lcu_size_log2; |
| WRITE_VREG(HEVC_SAO_CTRL0, data32); |
| #if 0 |
| #ifdef LOSLESS_COMPRESS_MODE |
| if ((get_double_write_mode(dec) & 0x10) == 0) |
| WRITE_VREG(HEVC_CM_BODY_START_ADDR, pic->mc_y_adr); |
| |
| if ((get_double_write_mode(dec) & 0x10) == 0) |
| WRITE_VREG(HEVC_CM_BODY_START_ADDR, pic->mc_y_adr); |
| if ((get_double_write_mode(dec) & 0x20) == 0) { |
| WRITE_VREG(HEVC_SAO_Y_START_ADDR, pic->dw_y_adr); |
| WRITE_VREG(HEVC_SAO_C_START_ADDR, pic->dw_u_v_adr); |
| WRITE_VREG(HEVC_SAO_Y_WPTR, pic->dw_y_adr); |
| WRITE_VREG(HEVC_SAO_C_WPTR, pic->dw_u_v_adr); |
| } else { |
| WRITE_VREG(HEVC_SAO_Y_START_ADDR, 0xffffffff); |
| WRITE_VREG(HEVC_SAO_C_START_ADDR, 0xffffffff); |
| } |
| WRITE_VREG(HEVC_CM_HEADER_START_ADDR, pic->header_adr); |
| if (dec->dw_mmu_enable) { |
| WRITE_VREG(HEVC_CM_HEADER_START_ADDR2, pic->dw_header_adr); |
| WRITE_VREG(HEVC_SAO_Y_START_ADDR, 0); |
| WRITE_VREG(HEVC_SAO_C_START_ADDR, 0); |
| } |
| |
| //WRITE_VREG(HEVC_SAO_Y_START_ADDR, DOUBLE_WRITE_YSTART_TEMP); |
| //WRITE_VREG(HEVC_CM_BODY_START_ADDR, pic->mc_y_adr); |
| #ifdef AVS3_10B_MMU |
| //WRITE_VREG(HEVC_CM_HEADER_START_ADDR, avs3_dec->cm_header_start + (pic->index * get_compress_header_size(dec))); |
| #endif |
| #ifdef AVS3_10B_MMU_DW |
| //if (dec->dw_mmu_enable) { |
| // WRITE_VREG(HEVC_CM_HEADER_START_ADDR2, pic->header_dw_adr); |
| //} |
| #endif |
| |
| #else |
| WRITE_VREG(HEVC_SAO_Y_START_ADDR, pic->mc_y_adr); |
| #endif |
| |
| data32 = (mc_buffer_size_u_v_h<<16)<<1; |
| WRITE_VREG(HEVC_SAO_Y_LENGTH ,data32); |
| |
| //WRITE_VREG(HEVC_SAO_C_START_ADDR,DOUBLE_WRITE_CSTART_TEMP); |
| |
| data32 = (mc_buffer_size_u_v_h<<16); |
| WRITE_VREG(HEVC_SAO_C_LENGTH ,data32); |
| //WRITE_VREG(HEVC_SAO_Y_WPTR ,DOUBLE_WRITE_YSTART_TEMP); |
| //WRITE_VREG(HEVC_SAO_C_WPTR ,DOUBLE_WRITE_CSTART_TEMP); |
| #endif |
| |
| #ifdef AVS3_10B_NV21 |
| data32 = READ_VREG(HEVC_SAO_CTRL1); |
| data32 &= (~0x3000); |
| data32 |= (MEM_MAP_MODE << 12); // [13:12] axi_aformat, 0-Linear, 1-32x32, 2-64x32 |
| data32 &= (~0x3); |
| data32 |= 0x1; // [1]:dw_disable [0]:cm_disable |
| WRITE_VREG(HEVC_SAO_CTRL1, data32); |
| |
| data32 = READ_VREG(HEVC_SAO_CTRL5); // [23:22] dw_v1_ctrl [21:20] dw_v0_ctrl [19:18] dw_h1_ctrl [17:16] dw_h0_ctrl |
| data32 &= ~(0xff << 16); // set them all 0 for H265_NV21 (no down-scale) |
| WRITE_VREG(HEVC_SAO_CTRL5, data32); |
| |
| data32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG); |
| data32 &= (~0x30); |
| data32 |= (MEM_MAP_MODE << 4); // [5:4] -- address_format 00:linear 01:32x32 10:64x32 |
| WRITE_VREG(HEVCD_IPP_AXIIF_CONFIG, data32); |
| #endif |
| |
| #ifndef AVS3_10B_NV21 |
| #ifdef AVS3_10B_MMU_DW |
| if (dec->dw_mmu_enable) { |
| WRITE_VREG(HEVC_DW_VH0_ADDDR, DOUBLE_WRITE_VH0_TEMP); |
| WRITE_VREG(HEVC_DW_VH1_ADDDR, DOUBLE_WRITE_VH1_TEMP); |
| } |
| #endif |
| #endif |
| |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, |
| "[c] cfgSAO .done.\n"); |
| } |
| |
| static void config_alf_hw(struct AVS3Decoder_s *dec) |
| { |
| /* |
| * Picture level ALF parameter configuration here |
| */ |
| struct avs3_decoder *avs3_dec = &dec->avs3_dec; |
| uint32_t data32; |
| int32_t i,j; |
| int32_t m_filters_per_group; |
| #ifdef USE_FORCED_ALF_PARAM |
| ALFParam forced_alf_cr; |
| forced_alf_cr.alf_flag = 1; |
| forced_alf_cr.num_coeff = 9; |
| forced_alf_cr.filters_per_group = 1; |
| forced_alf_cr.component_id = 2; |
| forced_alf_cr.coeff_multi[0][0] = -3; |
| forced_alf_cr.coeff_multi[0][1] = -3; |
| forced_alf_cr.coeff_multi[0][2] = 4; |
| forced_alf_cr.coeff_multi[0][3] = 7; |
| forced_alf_cr.coeff_multi[0][4] = 6; |
| forced_alf_cr.coeff_multi[0][5] = -1; |
| forced_alf_cr.coeff_multi[0][6] = 3; |
| forced_alf_cr.coeff_multi[0][7] = 6; |
| forced_alf_cr.coeff_multi[0][8] = 0; |
| #endif |
| |
| ALFParam *m_alfPictureParam_y = &avs3_dec->m_alfPictureParam[0]; |
| ALFParam *m_alfPictureParam_cb = &avs3_dec->m_alfPictureParam[1]; |
| #ifdef USE_FORCED_ALF_PARAM |
| ALFParam *m_alfPictureParam_cr = &forced_alf_cr; // &avs3_dec->m_alfPictureParam[2]; |
| #else |
| ALFParam *m_alfPictureParam_cr = &avs3_dec->m_alfPictureParam[2]; |
| #endif |
| |
| printf("[t]alfy,cidx(%d),flag(%d),filters_per_group(%d),filter_pattern[0]=0x%x,[15]=0x%x\n", |
| m_alfPictureParam_y->component_id, |
| m_alfPictureParam_y->alf_flag, |
| m_alfPictureParam_y->filters_per_group, |
| m_alfPictureParam_y->filter_pattern[0],m_alfPictureParam_y->filter_pattern[15]); |
| printf("[t]alfy,num_coeff(%d),coeff_multi[0][0]=0x%x,[0][1]=0x%x,[1][0]=0x%x,[1][1]=0x%x\n", |
| m_alfPictureParam_y->num_coeff, |
| m_alfPictureParam_y->coeff_multi[0][0], |
| m_alfPictureParam_y->coeff_multi[0][1], |
| m_alfPictureParam_y->coeff_multi[1][0], |
| m_alfPictureParam_y->coeff_multi[1][1]); |
| |
| // Cr |
| for (i=0;i<16;i++) dec->m_varIndTab[i] = 0; |
| for (j=0;j<16;j++) for (i=0;i<9;i++) dec->m_filterCoeffSym[j][i] = 0; |
| reconstructCoefInfo(dec, 2, m_alfPictureParam_cr); |
| data32 = ((dec->m_filterCoeffSym[0][4] & 0xf ) << 28) | |
| ((dec->m_filterCoeffSym[0][3] & 0x7f) << 21) | |
| ((dec->m_filterCoeffSym[0][2] & 0x7f) << 14) | |
| ((dec->m_filterCoeffSym[0][1] & 0x7f) << 7) | |
| ((dec->m_filterCoeffSym[0][0] & 0x7f) << 0); |
| WRITE_VREG(HEVC_DBLK_CFGD, data32); |
| data32 = ((dec->m_filterCoeffSym[0][8] & 0x7f) << 24) | |
| ((dec->m_filterCoeffSym[0][7] & 0x7f) << 17) | |
| ((dec->m_filterCoeffSym[0][6] & 0x7f) << 10) | |
| ((dec->m_filterCoeffSym[0][5] & 0x7f) << 3) | |
| (((dec->m_filterCoeffSym[0][4]>>4) & 0x7 ) << 0); |
| WRITE_VREG(HEVC_DBLK_CFGD, data32); |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, |
| "[c] pic_alf_on_cr(%d), alf_cr_coef(%d %d %d %d %d %d %d %d %d)\n", m_alfPictureParam_cr->alf_flag, |
| dec->m_filterCoeffSym[0][0],dec->m_filterCoeffSym[0][1],dec->m_filterCoeffSym[0][2], |
| dec->m_filterCoeffSym[0][3],dec->m_filterCoeffSym[0][4],dec->m_filterCoeffSym[0][5], |
| dec->m_filterCoeffSym[0][6],dec->m_filterCoeffSym[0][7],dec->m_filterCoeffSym[0][8]); |
| |
| // Cb |
| for (j=0;j<16;j++) for (i=0;i<9;i++) dec->m_filterCoeffSym[j][i] = 0; |
| reconstructCoefInfo(dec, 1, m_alfPictureParam_cb); |
| data32 = ((dec->m_filterCoeffSym[0][4] & 0xf ) << 28) | |
| ((dec->m_filterCoeffSym[0][3] & 0x7f) << 21) | |
| ((dec->m_filterCoeffSym[0][2] & 0x7f) << 14) | |
| ((dec->m_filterCoeffSym[0][1] & 0x7f) << 7) | |
| ((dec->m_filterCoeffSym[0][0] & 0x7f) << 0); |
| WRITE_VREG(HEVC_DBLK_CFGD, data32); |
| data32 = ((dec->m_filterCoeffSym[0][8] & 0x7f) << 24) | |
| ((dec->m_filterCoeffSym[0][7] & 0x7f) << 17) | |
| ((dec->m_filterCoeffSym[0][6] & 0x7f) << 10) | |
| ((dec->m_filterCoeffSym[0][5] & 0x7f) << 3) | |
| (((dec->m_filterCoeffSym[0][4]>>4) & 0x7 ) << 0); |
| WRITE_VREG(HEVC_DBLK_CFGD, data32); |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, |
| "[c] pic_alf_on_cb(%d), alf_cb_coef(%d %d %d %d %d %d %d %d %d)\n", m_alfPictureParam_cb->alf_flag, |
| dec->m_filterCoeffSym[0][0],dec->m_filterCoeffSym[0][1],dec->m_filterCoeffSym[0][2], |
| dec->m_filterCoeffSym[0][3],dec->m_filterCoeffSym[0][4],dec->m_filterCoeffSym[0][5], |
| dec->m_filterCoeffSym[0][6],dec->m_filterCoeffSym[0][7],dec->m_filterCoeffSym[0][8]); |
| |
| // Y |
| for (j=0;j<16;j++) for (i=0;i<9;i++) dec->m_filterCoeffSym[j][i] = 0; |
| reconstructCoefInfo(dec, 0, m_alfPictureParam_y); |
| data32 = ((dec->m_varIndTab[7] & 0xf) << 28) | ((dec->m_varIndTab[6] & 0xf) << 24) | |
| ((dec->m_varIndTab[5] & 0xf) << 20) | ((dec->m_varIndTab[4] & 0xf) << 16) | |
| ((dec->m_varIndTab[3] & 0xf) << 12) | ((dec->m_varIndTab[2] & 0xf) << 8) | |
| ((dec->m_varIndTab[1] & 0xf) << 4) | ((dec->m_varIndTab[0] & 0xf) << 0); |
| WRITE_VREG(HEVC_DBLK_CFGD, data32); |
| data32 = ((dec->m_varIndTab[15] & 0xf) << 28) | ((dec->m_varIndTab[14] & 0xf) << 24) | |
| ((dec->m_varIndTab[13] & 0xf) << 20) | ((dec->m_varIndTab[12] & 0xf) << 16) | |
| ((dec->m_varIndTab[11] & 0xf) << 12) | ((dec->m_varIndTab[10] & 0xf) << 8) | |
| ((dec->m_varIndTab[ 9] & 0xf) << 4) | ((dec->m_varIndTab[ 8] & 0xf) << 0); |
| WRITE_VREG(HEVC_DBLK_CFGD, data32); |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, |
| "[c] pic_alf_on_y(%d), alf_y_tab(%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d)\n", m_alfPictureParam_y->alf_flag, |
| dec->m_varIndTab[ 0],dec->m_varIndTab[ 1],dec->m_varIndTab[ 2],dec->m_varIndTab[ 3], |
| dec->m_varIndTab[ 4],dec->m_varIndTab[ 5],dec->m_varIndTab[ 6],dec->m_varIndTab[ 7], |
| dec->m_varIndTab[ 8],dec->m_varIndTab[ 9],dec->m_varIndTab[10],dec->m_varIndTab[11], |
| dec->m_varIndTab[12],dec->m_varIndTab[13],dec->m_varIndTab[14],dec->m_varIndTab[15]); |
| |
| m_filters_per_group = (m_alfPictureParam_y->alf_flag == 0) ? 1 : m_alfPictureParam_y->filters_per_group; |
| for (i=0;i<m_filters_per_group;i++) { |
| data32 = ((dec->m_filterCoeffSym[i][4] & 0xf ) << 28) | |
| ((dec->m_filterCoeffSym[i][3] & 0x7f) << 21) | |
| ((dec->m_filterCoeffSym[i][2] & 0x7f) << 14) | |
| ((dec->m_filterCoeffSym[i][1] & 0x7f) << 7) | |
| ((dec->m_filterCoeffSym[i][0] & 0x7f) << 0); |
| WRITE_VREG(HEVC_DBLK_CFGD, data32); |
| data32 = ((i == m_filters_per_group-1) << 31) | // [31] last indication |
| ((dec->m_filterCoeffSym[i][8] & 0x7f) << 24) | |
| ((dec->m_filterCoeffSym[i][7] & 0x7f) << 17) | |
| ((dec->m_filterCoeffSym[i][6] & 0x7f) << 10) | |
| ((dec->m_filterCoeffSym[i][5] & 0x7f) << 3) | |
| (((dec->m_filterCoeffSym[i][4]>>4) & 0x7 ) << 0); |
| WRITE_VREG(HEVC_DBLK_CFGD, data32); |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, |
| "[c] alf_y_coef[%d](%d %d %d %d %d %d %d %d %d)\n",i,dec->m_filterCoeffSym[i][0],dec->m_filterCoeffSym[i][1],dec->m_filterCoeffSym[i][2], |
| dec->m_filterCoeffSym[i][3],dec->m_filterCoeffSym[i][4],dec->m_filterCoeffSym[i][5], |
| dec->m_filterCoeffSym[i][6],dec->m_filterCoeffSym[i][7],dec->m_filterCoeffSym[i][8]); |
| } |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, |
| "[c] cfgALF .done.\n"); |
| } |
| |
| static u32 init_cuva_size; |
| |
| static int cuva_data_is_available(struct AVS3Decoder_s *dec, u32 reg_val) |
| { |
| |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, |
| "%s:reg_val: %u \n", |
| __func__, reg_val); |
| if (reg_val != 0 && reg_val != init_cuva_size) |
| return 1; |
| else |
| return 0; |
| } |
| |
| void config_cuva_buf(struct AVS3Decoder_s *dec) |
| { |
| WRITE_VREG(AVS3_CUVA_ADR, dec->cuva_phy_addr); |
| init_cuva_size = (dec->cuva_size >> 4) << 16; |
| WRITE_VREG(AVS3_CUVA_DATA_SIZE, init_cuva_size); |
| } |
| |
| static void set_cuva_data(struct AVS3Decoder_s *dec) |
| { |
| int i; |
| unsigned short *cuva_adr; |
| unsigned int size_reg_val = |
| READ_VREG(AVS3_CUVA_DATA_SIZE); |
| unsigned int cuva_count = 0; |
| int cuva_size = 0; |
| struct avs3_frame_s *pic = dec->avs3_dec.cur_pic; |
| if (pic == NULL || 0 == cuva_data_is_available(dec, size_reg_val)) { |
| avs3_print(dec, AVS3_DBG_HDR_INFO, |
| "%s:pic 0x%p or data not available\n", |
| __func__, pic); |
| return; |
| } |
| |
| cuva_adr = (unsigned short *)dec->cuva_addr; |
| cuva_count = ((size_reg_val >> 16) << 4) >> 1; |
| cuva_size = dec->cuva_size; |
| |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, |
| "%s:pic 0x%p cuva_count(%d) cuva_size(%d) hdr_flag 0x%x\n", |
| __func__, pic, cuva_count, cuva_size, dec->hdr_flag); |
| if (cuva_size > 0 && cuva_count > 0) { |
| int new_size; |
| char *new_buf; |
| |
| new_size = cuva_size; |
| new_buf = vzalloc(new_size); |
| if (new_buf) { |
| unsigned char *p = new_buf; |
| int len = 0; |
| pic->cuva_data_buf = new_buf; |
| |
| for (i = 0; i < cuva_count; i += 4) { |
| int j; |
| |
| for (j = 0; j < 4; j++) { |
| unsigned short aa = cuva_adr[i + 3 - j]; |
| *p = aa & 0xff; |
| p++; |
| len++; |
| } |
| } |
| if (len > 0) { |
| pic->cuva_data_size = len; |
| } |
| |
| if (pic->cuva_data_buf[0] == 0x26 |
| && pic->cuva_data_buf[1] == 0x00 |
| && pic->cuva_data_buf[2] == 0x04 |
| && pic->cuva_data_buf[3] == 0x00 |
| && pic->cuva_data_buf[4] == 0x05) { |
| dec->hdr_flag |= HDR_CUVA_MASK; |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, |
| "cuva stream: (size %d)\n", pic->cuva_data_size); |
| } else { |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, |
| " other hdr stream (size %d)\n", pic->cuva_data_size); |
| } |
| |
| if (get_dbg_flag(dec) & AVS3_DBG_HDR_DATA) { |
| for (i = 0; i < pic->cuva_data_size; i++) { |
| pr_info("%02x ", pic->cuva_data_buf[i]); |
| if (((i + 1) & 0xf) == 0) |
| pr_info("\n"); |
| } |
| pr_info("\n"); |
| } |
| |
| } else { |
| avs3_print(dec, 0, "new buf alloc failed\n"); |
| if (pic->cuva_data_buf) |
| vfree(pic->cuva_data_buf); |
| pic->cuva_data_buf = NULL; |
| pic->cuva_data_size = 0; |
| } |
| } |
| } |
| |
| static void release_cuva_data(struct avs3_frame_s *pic) |
| { |
| if (pic == NULL) |
| return; |
| if (pic->cuva_data_buf) { |
| vfree(pic->cuva_data_buf); |
| } |
| pic->cuva_data_buf = NULL; |
| pic->cuva_data_size = 0; |
| } |
| |
| static void avs3_config_work_space_hw(struct AVS3Decoder_s *dec) |
| { |
| DEC_CTX * ctx = &dec->avs3_dec.ctx; |
| struct BuffInfo_s *buf_spec = dec->work_space_buf; |
| u32 width = dec->avs3_dec.img.width ? dec->avs3_dec.img.width : dec->init_pic_w; |
| u32 height = dec->avs3_dec.img.height ? dec->avs3_dec.img.height : dec->init_pic_h; |
| u8 is_bit_depth_10 = (ctx->info.bit_depth_internal == 8) ? 0 : 1; |
| |
| #ifdef LOSLESS_COMPRESS_MODE |
| int losless_comp_header_size = compute_losless_comp_header_size( |
| dec, width, height); |
| int losless_comp_body_size = compute_losless_comp_body_size( |
| dec, width, height, is_bit_depth_10); |
| #endif |
| #ifdef AVS3_10B_MMU |
| unsigned int data32; |
| #endif |
| if (debug && dec->init_flag == 0) |
| avs3_print(dec, 0, |
| "%s %x %x %x %x %x %x %x %x %x %x %x %x %x\n", |
| __func__, |
| buf_spec->ipp.buf_start, |
| buf_spec->start_adr, |
| buf_spec->short_term_rps.buf_start, |
| buf_spec->rcs.buf_start, |
| buf_spec->sps.buf_start, |
| buf_spec->pps.buf_start, |
| buf_spec->sao_up.buf_start, |
| buf_spec->swap_buf.buf_start, |
| buf_spec->swap_buf2.buf_start, |
| buf_spec->scalelut.buf_start, |
| buf_spec->dblk_para.buf_start, |
| buf_spec->dblk_data.buf_start, |
| buf_spec->dblk_data2.buf_start); |
| WRITE_VREG(HEVCD_IPP_LINEBUFF_BASE, buf_spec->ipp.buf_start); |
| if ((debug & AVS3_DBG_SEND_PARAM_WITH_REG) == 0) |
| WRITE_VREG(HEVC_RPM_BUFFER, (u32)dec->rpm_phy_addr); |
| WRITE_VREG(AVS3_ALF_SWAP_BUFFER, buf_spec->short_term_rps.buf_start); |
| WRITE_VREG(HEVC_RCS_BUFFER, buf_spec->rcs.buf_start); |
| //WRITE_VREG(HEVC_SPS_BUFFER, buf_spec->sps.buf_start); |
| //WRITE_VREG(HEVC_PPS_BUFFER, buf_spec->pps.buf_start); |
| WRITE_VREG(AVS3_SBAC_TOP_BUFFER, buf_spec->sbac_top.buf_start); |
| //WRITE_VREG(HEVC_SAO_UP, buf_spec->sao_up.buf_start); |
| #ifdef AVS3_10B_MMU |
| WRITE_VREG(AVS3_MMU_MAP_BUFFER, dec->frame_mmu_map_phy_addr); |
| #else |
| WRITE_VREG(HEVC_STREAM_SWAP_BUFFER, buf_spec->swap_buf.buf_start); |
| #endif |
| #ifdef AVS3_10B_MMU_DW |
| if (dec->dw_mmu_enable) { |
| //WRITE_VREG(HEVC_ASSIST_MMU_MAP_ADDR2, FRAME_MMU_MAP_ADDR_DW); |
| WRITE_VREG(HEVC_SAO_MMU_DMA_CTRL2, dec->dw_frame_mmu_map_phy_addr); |
| } |
| #endif |
| WRITE_VREG(HEVC_STREAM_SWAP_BUFFER2, buf_spec->swap_buf2.buf_start); |
| WRITE_VREG(HEVC_SCALELUT, buf_spec->scalelut.buf_start); |
| #ifndef FOR_S5 |
| if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { |
| if (buf_spec->max_width <= 4096 && buf_spec->max_height <= 2304) |
| WRITE_VREG(HEVC_DBLK_CFG3, 0x404010); //default value |
| else |
| WRITE_VREG(HEVC_DBLK_CFG3, 0x808020); // make left storage 2 x 4k] |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, |
| "HEVC_DBLK_CFG3 = %x\n", READ_VREG(HEVC_DBLK_CFG3)); |
| } |
| #endif |
| /* cfg_p_addr */ |
| WRITE_VREG(HEVC_DBLK_CFG4, buf_spec->dblk_para.buf_start); |
| /* cfg_d_addr */ |
| WRITE_VREG(HEVC_DBLK_CFG5, buf_spec->dblk_data.buf_start); |
| |
| WRITE_VREG(HEVC_DBLK_CFGE, buf_spec->dblk_data2.buf_start); |
| |
| #ifdef LOSLESS_COMPRESS_MODE |
| data32 = READ_VREG(HEVC_SAO_CTRL5); |
| #if 1 |
| data32 &= ~(1<<9); |
| #else |
| if (params->p.bit_depth != 0x00) |
| data32 &= ~(1<<9); |
| else |
| data32 |= (1<<9); |
| #endif |
| WRITE_VREG(HEVC_SAO_CTRL5, data32); |
| #ifdef AVS3_10B_MMU |
| /*bit[4] : paged_mem_mode*/ |
| WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (0x1 << 4)); |
| WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, 0); |
| #else |
| /* bit[3] smem mode*/ |
| WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (0<<3)); |
| |
| WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, (losless_comp_body_size >> 5)); |
| #endif |
| /*WRITE_VREG(HEVCD_MPP_DECOMP_CTL2,(losless_comp_body_size >> 5));*/ |
| /*WRITE_VREG(HEVCD_MPP_DECOMP_CTL3,(0xff<<20) | (0xff<<10) | 0xff);*/ |
| /*8-bit mode */ |
| WRITE_VREG(HEVC_CM_BODY_LENGTH, losless_comp_body_size); |
| WRITE_VREG(HEVC_CM_HEADER_OFFSET, losless_comp_body_size); |
| WRITE_VREG(HEVC_CM_HEADER_LENGTH, losless_comp_header_size); |
| #else |
| WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x1 << 31); |
| #endif |
| |
| #ifdef AVS3_10B_MMU |
| WRITE_VREG(HEVC_SAO_MMU_VH0_ADDR, buf_spec->mmu_vbh.buf_start); |
| WRITE_VREG(HEVC_SAO_MMU_VH1_ADDR, buf_spec->mmu_vbh.buf_start |
| + VBH_BUF_SIZE(buf_spec)); |
| /*data32 = READ_VREG(HEVC_SAO_CTRL9);*/ |
| /*data32 |= 0x1;*/ |
| /*WRITE_VREG(HEVC_SAO_CTRL9, data32);*/ |
| |
| /* use HEVC_CM_HEADER_START_ADDR */ |
| data32 = READ_VREG(HEVC_SAO_CTRL5); |
| data32 |= (1<<10); |
| #if 0 |
| if (debug & AVS3_DBG_FORCE_UNCOMPRESS) |
| data32 |= 0x80; |
| #endif |
| WRITE_VREG(HEVC_SAO_CTRL5, data32); |
| |
| #endif |
| |
| #ifdef AVS3_10B_MMU_DW |
| if (dec->dw_mmu_enable) { |
| u32 data_tmp; |
| data_tmp = READ_VREG(HEVC_SAO_CTRL9); |
| data_tmp |= (1<<10); |
| WRITE_VREG(HEVC_SAO_CTRL9, data_tmp); |
| |
| WRITE_VREG(HEVC_CM_BODY_LENGTH2,losless_comp_body_size); |
| WRITE_VREG(HEVC_CM_HEADER_OFFSET2,losless_comp_body_size); |
| WRITE_VREG(HEVC_CM_HEADER_LENGTH2,losless_comp_header_size); |
| |
| WRITE_VREG(HEVC_SAO_MMU_VH0_ADDR2, buf_spec->mmu_vbh_dw.buf_start); |
| WRITE_VREG(HEVC_SAO_MMU_VH1_ADDR2, buf_spec->mmu_vbh_dw.buf_start + DW_VBH_BUF_SIZE(buf_spec)); |
| |
| /* use HEVC_CM_HEADER_START_ADDR */ |
| data32 = READ_VREG(HEVC_SAO_CTRL5); |
| data32 |= (1<<15); |
| WRITE_VREG(HEVC_SAO_CTRL5, data32); |
| } |
| #endif |
| |
| WRITE_VREG(LMEM_DUMP_ADR, (u32)dec->lmem_phy_addr); |
| |
| WRITE_VREG(HEVC_MPRED_ABV_START_ADDR, buf_spec->mpred_above.buf_start); |
| |
| #ifdef CO_MV_COMPRESS |
| //if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_T7) { |
| data32 = READ_VREG(HEVC_MPRED_CTRL4); |
| data32 |= (1 << 1); |
| WRITE_VREG(HEVC_MPRED_CTRL4, data32); |
| //} |
| #endif |
| data32 = READ_VREG(HEVC_MPRED_CTRL4); |
| data32 |= (1<<26); //enable AVS3 mode |
| WRITE_VREG(HEVC_MPRED_CTRL4, data32); |
| } |
| |
| static void decomp_perfcount_reset(void) |
| { |
| if (debug & AVS3_DBG_CACHE) |
| pr_info("[cache_util.c] Entered decomp_perfcount_reset...\n"); |
| WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)0x1); |
| WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)0x0); |
| return; |
| } |
| |
| static void mcrcc_perfcount_reset(void) |
| { |
| if (debug & AVS3_DBG_CACHE) |
| pr_info("[cache_util.c] Entered mcrcc_perfcount_reset...\n"); |
| WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)0x1); |
| WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)0x0); |
| return; |
| } |
| |
| #ifdef TMP_DEBUG |
| |
| static void avs2_init_decoder_hw(struct AVS3Decoder_s *dec) |
| { |
| unsigned int data32; |
| unsigned int decode_mode; |
| int i; |
| |
| data32 = READ_VREG(HEVC_PARSER_INT_CONTROL); |
| |
| /* set bit 31~29 to 3 if HEVC_STREAM_FIFO_CTL[29] is 1 */ |
| data32 &= ~(7 << 29); |
| data32 |= (3 << 29); |
| |
| data32 = data32 | |
| (1 << 24) |/*stream_buffer_empty_int_amrisc_enable*/ |
| (1 << 22) |/*stream_fifo_empty_int_amrisc_enable*/ |
| (1 << 7) |/*dec_done_int_cpu_enable*/ |
| (1 << 4) |/*startcode_found_int_cpu_enable*/ |
| (0 << 3) |/*startcode_found_int_amrisc_enable*/ |
| (1 << 0); /*parser_int_enable*/ |
| |
| WRITE_VREG(HEVC_PARSER_INT_CONTROL, data32); |
| |
| data32 = READ_VREG(HEVC_SHIFT_STATUS); |
| data32 = data32 | |
| (0 << 1) |/*emulation_check_off VP9 |
| do not have emulation*/ |
| (1 << 0);/*startcode_check_on*/ |
| |
| WRITE_VREG(HEVC_SHIFT_STATUS, data32); |
| WRITE_VREG(HEVC_SHIFT_CONTROL, |
| (6 << 20) | /* emu_push_bits (6-bits for AVS2)*/ |
| (0 << 19) | /* emu_3_enable, maybe turned on in microcode*/ |
| (0 << 18) | /* emu_2_enable, maybe turned on in microcode*/ |
| (0 << 17) | /* emu_1_enable, maybe turned on in microcode*/ |
| (0 << 16) | /* emu_0_enable, maybe turned on in microcode*/ |
| (0 << 14) | /*disable_start_code_protect*/ |
| (3 << 6) | /* sft_valid_wr_position*/ |
| (2 << 4) | /* emulate_code_length_sub_1*/ |
| (2 << 1) | /* start_code_length_sub_1*/ |
| (1 << 0)); /* stream_shift_enable*/ |
| |
| WRITE_VREG(HEVC_SHIFT_LENGTH_PROTECT, |
| (0 << 30) | /*data_protect_fill_00_enable*/ |
| (1 << 29)); /*data_protect_fill_ff_enable*/ |
| |
| WRITE_VREG(HEVC_CABAC_CONTROL, (1 << 0));/*cabac_enable*/ |
| |
| WRITE_VREG(HEVC_PARSER_CORE_CONTROL, (1 << 0));/* hevc_parser_core_clk_en*/ |
| |
| WRITE_VREG(HEVC_DEC_STATUS_REG, 0); |
| |
| /*Initial IQIT_SCALELUT memory -- just to avoid X in simulation*/ |
| if (is_rdma_enable()) |
| rdma_back_end_work(dec->rdma_phy_adr, RDMA_SIZE); |
| else { |
| WRITE_VREG(HEVC_IQIT_SCALELUT_WR_ADDR, 0);/*cfg_p_addr*/ |
| for (i = 0; i < 1024; i++) |
| WRITE_VREG(HEVC_IQIT_SCALELUT_DATA, 0); |
| } |
| |
| #ifdef ENABLE_SWAP_TEST |
| WRITE_VREG(HEVC_STREAM_SWAP_TEST, 100); |
| #else |
| WRITE_VREG(HEVC_STREAM_SWAP_TEST, 0); |
| #endif |
| if (!dec->m_ins_flag) |
| decode_mode = DECODE_MODE_SINGLE; |
| else if (vdec_frame_based(hw_to_vdec(dec))) |
| decode_mode = DECODE_MODE_MULTI_FRAMEBASE; |
| else |
| decode_mode = DECODE_MODE_MULTI_STREAMBASE; |
| dec->start_decoding_flag = 3; |
| decode_mode |= (dec->start_decoding_flag << 16); |
| |
| WRITE_VREG(DECODE_MODE, decode_mode); |
| WRITE_VREG(HEVC_DECODE_SIZE, 0); |
| WRITE_VREG(HEVC_DECODE_COUNT, 0); |
| #ifdef DYN_CACHE |
| if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_S5) { |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, "HEVC DYN MCRCC\n"); |
| WRITE_VREG(HEVCD_IPP_DYN_CACHE,0x2b);//enable new mcrcc |
| } |
| #endif |
| |
| /*Send parser_cmd*/ |
| WRITE_VREG(HEVC_PARSER_CMD_WRITE, (1 << 16) | (0 << 0)); |
| for (i = 0; i < PARSER_CMD_NUMBER; i++) |
| WRITE_VREG(HEVC_PARSER_CMD_WRITE, parser_cmd[i]); |
| WRITE_VREG(HEVC_PARSER_CMD_SKIP_0, PARSER_CMD_SKIP_CFG_0); |
| WRITE_VREG(HEVC_PARSER_CMD_SKIP_1, PARSER_CMD_SKIP_CFG_1); |
| WRITE_VREG(HEVC_PARSER_CMD_SKIP_2, PARSER_CMD_SKIP_CFG_2); |
| |
| WRITE_VREG(HEVC_PARSER_IF_CONTROL, |
| (1 << 9) | /* parser_alf_if_en*/ |
| /* (1 << 8) |*/ /*sao_sw_pred_enable*/ |
| (1 << 5) | /*parser_sao_if_en*/ |
| (1 << 2) | /*parser_mpred_if_en*/ |
| (1 << 0) /*parser_scaler_if_en*/ |
| ); |
| |
| #ifdef MULTI_INSTANCE_SUPPORT |
| WRITE_VREG(HEVC_MPRED_INT_STATUS, (1<<31)); |
| |
| WRITE_VREG(HEVC_PARSER_RESULT_3, 0xffffffff); |
| |
| for (i = 0; i < 8; i++) |
| data32 = READ_VREG(HEVC_MPRED_ABV_START_ADDR); |
| |
| WRITE_VREG(DOS_SW_RESET3, (1<<18)); /* reset mpred */ |
| WRITE_VREG(DOS_SW_RESET3, 0); |
| WRITE_VREG(HEVC_MPRED_ABV_START_ADDR, data32); |
| WRITE_VREG(HEVC_MPRED_ABV_START_ADDR, data32); |
| WRITE_VREG(HEVC_MPRED_ABV_START_ADDR, data32); |
| #endif |
| |
| return; |
| } |
| |
| #else |
| static |
| #endif |
| void avs3_init_decoder_hw(struct AVS3Decoder_s *dec) |
| { |
| unsigned int data32; |
| unsigned int decode_mode; |
| int i; |
| /*if (debug & AVS3_DBG_BUFMGR_MORE) |
| pr_info("%s\n", __func__);*/ |
| data32 = READ_VREG(HEVC_PARSER_INT_CONTROL); |
| #if 1 |
| /* set bit 31~29 to 3 if HEVC_STREAM_FIFO_CTL[29] is 1 */ |
| data32 &= ~(7 << 29); |
| data32 |= (3 << 29); |
| #endif |
| data32 = data32 | |
| (1 << 24) |/*stream_buffer_empty_int_amrisc_enable*/ |
| (1 << 22) |/*stream_fifo_empty_int_amrisc_enable*/ |
| (1 << 7) |/*dec_done_int_cpu_enable*/ |
| (1 << 4) |/*startcode_found_int_cpu_enable*/ |
| (0 << 3) |/*startcode_found_int_amrisc_enable*/ |
| (1 << 0) /*parser_int_enable*/ |
| ; |
| WRITE_VREG(HEVC_PARSER_INT_CONTROL, data32); |
| |
| data32 = READ_VREG(HEVC_SHIFT_STATUS); |
| data32 = data32 | |
| (0 << 1) |/*emulation_check_off VP9 |
| do not have emulation*/ |
| (1 << 0)/*startcode_check_on*/ |
| ; |
| WRITE_VREG(HEVC_SHIFT_STATUS, data32); |
| WRITE_VREG(HEVC_SHIFT_CONTROL, |
| (6 << 20) | /* emu_push_bits (6-bits for AVS3)*/ |
| (0 << 19) | /* emu_3_enable, maybe turned on in microcode*/ |
| (0 << 18) | /* emu_2_enable, maybe turned on in microcode*/ |
| (0 << 17) | /* emu_1_enable, maybe turned on in microcode*/ |
| (0 << 16) | /* emu_0_enable, maybe turned on in microcode*/ |
| (0 << 14) | /*disable_start_code_protect*/ |
| (3 << 6) | /* sft_valid_wr_position*/ |
| (2 << 4) | /* emulate_code_length_sub_1*/ |
| (2 << 1) | /* start_code_length_sub_1*/ |
| (1 << 0) /* stream_shift_enable*/ |
| ); |
| |
| WRITE_VREG(HEVC_SHIFT_LENGTH_PROTECT, |
| (0 << 30) | /*data_protect_fill_00_enable*/ |
| (1 << 29) /*data_protect_fill_ff_enable*/ |
| ); |
| WRITE_VREG(HEVC_CABAC_CONTROL, |
| (1 << 0)/*cabac_enable*/ |
| ); |
| |
| WRITE_VREG(HEVC_PARSER_CORE_CONTROL, |
| (1 << 0)/* hevc_parser_core_clk_en*/ |
| ); |
| |
| WRITE_VREG(HEVC_DEC_STATUS_REG, 0); |
| |
| /*Initial IQIT_SCALELUT memory -- just to avoid X in simulation*/ |
| if (is_rdma_enable()) |
| rdma_back_end_work(dec->rdma_phy_adr, RDMA_SIZE); |
| else { |
| if ((debug & AVS3_DBG_DISABLE_IQIT_SCALELUT_INIT) == 0) { |
| WRITE_VREG(HEVC_IQIT_SCALELUT_WR_ADDR, 0);/*cfg_p_addr*/ |
| for (i = 0; i < 1024; i++) |
| WRITE_VREG(HEVC_IQIT_SCALELUT_DATA, 0); |
| } |
| } |
| |
| #ifdef ENABLE_SWAP_TEST |
| WRITE_VREG(HEVC_STREAM_SWAP_TEST, 100); |
| #else |
| WRITE_VREG(HEVC_STREAM_SWAP_TEST, 0); |
| #endif |
| if (!dec->m_ins_flag) |
| decode_mode = DECODE_MODE_SINGLE; |
| else if (vdec_frame_based(hw_to_vdec(dec))) |
| decode_mode = DECODE_MODE_MULTI_FRAMEBASE; |
| else |
| decode_mode = DECODE_MODE_MULTI_STREAMBASE; |
| if (dec->avs3_dec.bufmgr_error_flag && |
| (error_handle_policy & 0x1)) { |
| dec->bufmgr_error_count++; |
| dec->avs3_dec.bufmgr_error_flag = 0; |
| if (dec->bufmgr_error_count > |
| (re_search_seq_threshold & 0xff) |
| && dec->frame_count > |
| ((re_search_seq_threshold >> 8) & 0xff)) { |
| //struct avs3_decoder *avs3_dec = &dec->avs3_dec; |
| dec->start_decoding_flag = 0; |
| //avs3_dec->hd.vec_flag = 1; |
| dec->skip_PB_before_I = 1; |
| avs3_print(dec, 0, |
| "!!Bufmgr error, search seq again (0x%x %d %d)\n", |
| error_handle_policy, |
| dec->frame_count, |
| dec->bufmgr_error_count); |
| dec->bufmgr_error_count = 0; |
| } |
| } |
| #ifdef FOR_S5 |
| /*to do..*/ |
| dec->start_decoding_flag = 3; |
| #endif |
| decode_mode |= (dec->start_decoding_flag << 16); |
| WRITE_VREG(DECODE_MODE, decode_mode); |
| WRITE_VREG(HEVC_DECODE_SIZE, 0); |
| WRITE_VREG(HEVC_DECODE_COUNT, 0); |
| #ifdef DYN_CACHE |
| if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_S5) { |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, "HEVC DYN MCRCC\n"); |
| WRITE_VREG(HEVCD_IPP_DYN_CACHE,0x2b);//enable new mcrcc} |
| } |
| #endif |
| /*Send parser_cmd*/ |
| WRITE_VREG(HEVC_PARSER_CMD_WRITE, (1 << 16) | (0 << 0)); |
| for (i = 0; i < PARSER_CMD_NUMBER; i++) |
| WRITE_VREG(HEVC_PARSER_CMD_WRITE, parser_cmd[i]); |
| WRITE_VREG(HEVC_PARSER_CMD_SKIP_0, PARSER_CMD_SKIP_CFG_0); |
| WRITE_VREG(HEVC_PARSER_CMD_SKIP_1, PARSER_CMD_SKIP_CFG_1); |
| WRITE_VREG(HEVC_PARSER_CMD_SKIP_2, PARSER_CMD_SKIP_CFG_2); |
| |
| WRITE_VREG(HEVC_PARSER_IF_CONTROL, |
| (1 << 9) | /* parser_alf_if_en*/ |
| /* (1 << 8) |*/ /*sao_sw_pred_enable*/ |
| (1 << 5) | /*parser_sao_if_en*/ |
| (1 << 2) | /*parser_mpred_if_en*/ |
| (1 << 0) /*parser_scaler_if_en*/ |
| ); |
| |
| #if 0 //def MULTI_INSTANCE_SUPPORT |
| WRITE_VREG(HEVC_MPRED_INT_STATUS, (1<<31)); |
| |
| WRITE_VREG(HEVC_PARSER_RESULT_3, 0xffffffff); |
| |
| for (i = 0; i < 8; i++) |
| data32 = READ_VREG(HEVC_MPRED_ABV_START_ADDR); |
| |
| WRITE_VREG(DOS_SW_RESET3, (1<<18)); /* reset mpred */ |
| WRITE_VREG(DOS_SW_RESET3, 0); |
| WRITE_VREG(HEVC_MPRED_ABV_START_ADDR, data32); |
| WRITE_VREG(HEVC_MPRED_ABV_START_ADDR, data32); |
| WRITE_VREG(HEVC_MPRED_ABV_START_ADDR, data32); |
| #endif |
| /*End of Multi-instance*/ |
| /*Changed to Start MPRED in microcode*/ |
| /* |
| pr_info("[test.c] Start MPRED\n"); |
| WRITE_VREG(HEVC_MPRED_INT_STATUS, |
| (1<<31) |
| ); |
| */ |
| |
| /*AVS3 default seq_wq_matrix config*/ |
| |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, |
| "Config AVS3 default seq_wq_matrix ...\n"); |
| /*4x4*/ |
| /* default seq_wq_matrix_4x4 begin address*/ |
| WRITE_VREG(HEVC_IQIT_SCALELUT_WR_ADDR, 64); |
| for (i = 0; i < 16; i++) |
| WRITE_VREG(HEVC_IQIT_SCALELUT_DATA, g_WqMDefault4x4[i]); |
| |
| /*8x8*/ |
| /*default seq_wq_matrix_8x8 begin address*/ |
| WRITE_VREG(HEVC_IQIT_SCALELUT_WR_ADDR, 0); |
| for (i = 0; i < 64; i++) |
| WRITE_VREG(HEVC_IQIT_SCALELUT_DATA, g_WqMDefault8x8[i]); |
| |
| WRITE_VREG(HEVCD_IPP_TOP_CNTL, |
| (0 << 1) | /*enable ipp*/ |
| (1 << 0) /*software reset ipp and mpp*/ |
| ); |
| WRITE_VREG(HEVCD_IPP_TOP_CNTL, |
| (1 << 1) | /*enable ipp*/ |
| (0 << 0) /*software reset ipp and mpp*/ |
| ); |
| #if 0 |
| /*AVS3_10B_NV21*/ |
| /*Enable NV21 reference read mode for MC*/ |
| WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x1 << 31); |
| #endif |
| /* Init dblk*/ |
| data32 = READ_VREG(HEVC_DBLK_CFGB); |
| data32 |= (5 << 0); |
| /* [3:0] cfg_video_type -> AVS3*/ |
| #ifndef FOR_S5 |
| data32 &= (~0x300); /*[8]:first write enable (compress) |
| [9]:double write enable (uncompress)*/ |
| if (get_double_write_mode(dec) == 0) |
| data32 |= (0x1 << 8); /*enable first write*/ |
| else if (get_double_write_mode(dec) == 0x10) |
| data32 |= (0x1 << 9); /*double write only*/ |
| else |
| data32 |= ((0x1 << 8) | (0x1 << 9)); |
| #endif |
| WRITE_VREG(HEVC_DBLK_CFGB, data32); |
| |
| WRITE_VREG(HEVC_DBLK_CFG0, (1<<18) | (1 << 0)); /* [0] rst_sync*/ |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, |
| "Bitstream level Init for DBLK .Done.\n"); |
| |
| if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { |
| mcrcc_perfcount_reset(); |
| decomp_perfcount_reset(); |
| } |
| |
| return; |
| } |
| |
| #ifdef CONFIG_HEVC_CLK_FORCED_ON |
| static void config_avs3_clk_forced_on(void) |
| { |
| unsigned int rdata32; |
| /*IQIT*/ |
| rdata32 = READ_VREG(HEVC_IQIT_CLK_RST_CTRL); |
| WRITE_VREG(HEVC_IQIT_CLK_RST_CTRL, rdata32 | (0x1 << 2)); |
| |
| /* DBLK*/ |
| rdata32 = READ_VREG(HEVC_DBLK_CFG0); |
| WRITE_VREG(HEVC_DBLK_CFG0, rdata32 | (0x1 << 2)); |
| |
| /* SAO*/ |
| rdata32 = READ_VREG(HEVC_SAO_CTRL1); |
| WRITE_VREG(HEVC_SAO_CTRL1, rdata32 | (0x1 << 2)); |
| |
| /*MPRED*/ |
| rdata32 = READ_VREG(HEVC_MPRED_CTRL1); |
| WRITE_VREG(HEVC_MPRED_CTRL1, rdata32 | (0x1 << 24)); |
| |
| /* PARSER*/ |
| rdata32 = READ_VREG(HEVC_STREAM_CONTROL); |
| WRITE_VREG(HEVC_STREAM_CONTROL, rdata32 | (0x1 << 15)); |
| rdata32 = READ_VREG(HEVC_SHIFT_CONTROL); |
| WRITE_VREG(HEVC_SHIFT_CONTROL, rdata32 | (0x1 << 15)); |
| rdata32 = READ_VREG(HEVC_CABAC_CONTROL); |
| WRITE_VREG(HEVC_CABAC_CONTROL, rdata32 | (0x1 << 13)); |
| rdata32 = READ_VREG(HEVC_PARSER_CORE_CONTROL); |
| WRITE_VREG(HEVC_PARSER_CORE_CONTROL, rdata32 | (0x1 << 15)); |
| rdata32 = READ_VREG(HEVC_PARSER_INT_CONTROL); |
| WRITE_VREG(HEVC_PARSER_INT_CONTROL, rdata32 | (0x1 << 15)); |
| rdata32 = READ_VREG(HEVC_PARSER_IF_CONTROL); |
| WRITE_VREG(HEVC_PARSER_IF_CONTROL, |
| rdata32 | (0x1 << 6) | (0x1 << 3) | (0x1 << 1)); |
| |
| /*IPP*/ |
| rdata32 = READ_VREG(HEVCD_IPP_DYNCLKGATE_CONFIG); |
| WRITE_VREG(HEVCD_IPP_DYNCLKGATE_CONFIG, rdata32 | 0xffffffff); |
| |
| /* MCRCC*/ |
| rdata32 = READ_VREG(HEVCD_MCRCC_CTL1); |
| WRITE_VREG(HEVCD_MCRCC_CTL1, rdata32 | (0x1 << 3)); |
| } |
| #endif |
| |
| static struct AVS3Decoder_s gAVS3Decoder; |
| |
| static void avs3_local_uninit(struct AVS3Decoder_s *dec) |
| { |
| dec->rpm_ptr = NULL; |
| dec->lmem_ptr = NULL; |
| if (dec->rpm_addr) { |
| decoder_dma_free_coherent(dec->rpm_mem_handle, |
| RPM_BUF_SIZE, dec->rpm_addr, |
| dec->rpm_phy_addr); |
| dec->rpm_addr = NULL; |
| } |
| |
| if (dec->cuva_addr) { |
| decoder_dma_free_coherent(dec->cuva_handle, |
| dec->cuva_size, dec->cuva_addr, |
| dec->cuva_phy_addr); |
| dec->cuva_addr = NULL; |
| } |
| #if (defined DEBUG_UCODE_LOG) || (defined DEBUG_CMD) |
| if (dec->ucode_log_addr) { |
| decoder_dma_free_coherent(dec->ucode_log_handle, |
| UCODE_LOG_BUF_SIZE, dec->ucode_log_addr, |
| dec->ucode_log_phy_addr); |
| dec->ucode_log_addr = NULL; |
| } |
| #endif |
| if (dec->lmem_addr) { |
| if (dec->lmem_phy_addr) |
| decoder_dma_free_coherent(dec->lmem_phy_handle, |
| LMEM_BUF_SIZE, dec->lmem_addr, |
| dec->lmem_phy_addr); |
| dec->lmem_addr = NULL; |
| } |
| |
| #ifdef AVS3_10B_MMU |
| if (dec->frame_mmu_map_addr) { |
| if (dec->frame_mmu_map_phy_addr) |
| decoder_dma_free_coherent(dec->frame_mmu_map_handle, |
| get_frame_mmu_map_size(), dec->frame_mmu_map_addr, |
| dec->frame_mmu_map_phy_addr); |
| dec->frame_mmu_map_addr = NULL; |
| } |
| #ifdef NEW_FB_CODE |
| if (dec->front_back_mode) { |
| if (dec->frame_mmu_map_phy_addr_1) |
| decoder_dma_free_coherent(dec->frame_mmu_map_handle_1, |
| get_frame_mmu_map_size(), dec->frame_mmu_map_addr_1, |
| dec->frame_mmu_map_phy_addr_1); |
| |
| dec->frame_mmu_map_addr_1 = NULL; |
| } |
| #endif |
| #endif |
| |
| #ifdef AVS3_10B_MMU_DW |
| if (dec->dw_frame_mmu_map_addr) { |
| if (dec->dw_frame_mmu_map_phy_addr) |
| decoder_dma_free_coherent(dec->frame_dw_mmu_map_handle, |
| get_frame_mmu_map_size(), dec->dw_frame_mmu_map_addr, |
| dec->dw_frame_mmu_map_phy_addr); |
| dec->dw_frame_mmu_map_addr = NULL; |
| } |
| #ifdef NEW_FB_CODE |
| if (dec->front_back_mode && dec->dw_frame_mmu_map_addr_1) { |
| if (dec->dw_frame_mmu_map_phy_addr_1) |
| decoder_dma_free_coherent(dec->frame_dw_mmu_map_handle_1, |
| get_frame_mmu_map_size(), dec->dw_frame_mmu_map_addr_1, |
| dec->dw_frame_mmu_map_phy_addr_1); |
| |
| dec->dw_frame_mmu_map_addr_1 = NULL; |
| } |
| #endif |
| #endif |
| |
| if (dec->gvs) |
| vfree(dec->gvs); |
| dec->gvs = NULL; |
| } |
| |
| static int avs3_local_init(struct AVS3Decoder_s *dec) |
| { |
| int ret = -1; |
| /*int losless_comp_header_size, losless_comp_body_size;*/ |
| |
| struct avs3_decoder *avs3_dec = &dec->avs3_dec; |
| struct BuffInfo_s *cur_buf_info = NULL; |
| unsigned bufspec_index = 0; |
| cur_buf_info = &dec->work_space_buf_store; |
| if (force_bufspec) { |
| bufspec_index = force_bufspec & 0xf; |
| pr_info("force buffer spec %d\n", force_bufspec & 0xf); |
| } else { |
| if (vdec_is_support_4k()) { |
| bufspec_index = 2; /* 8k */ |
| } else |
| bufspec_index = 0;/* 1080p */ |
| } |
| pr_info("buffer spec %d\n", bufspec_index); |
| memcpy(cur_buf_info, &amvavs3_workbuff_spec[bufspec_index], |
| sizeof(struct BuffInfo_s)); |
| |
| cur_buf_info->start_adr = dec->buf_start; |
| #ifndef AVS3_10B_MMU |
| dec->mc_buf_spec.buf_end = dec->buf_start + dec->buf_size; |
| #endif |
| |
| init_buff_spec(dec, cur_buf_info); |
| |
| avs3_bufmgr_init(&dec->avs3_dec); |
| //init_avs3_decoder(&dec->avs3_dec); |
| |
| #ifdef AVS3_10B_MMU |
| avs3_dec_init(dec, cur_buf_info, NULL); |
| #else |
| dec->mc_buf_spec.buf_start = (cur_buf_info->end_adr + 0xffff) |
| & (~0xffff); |
| dec->mc_buf_spec.buf_size = (dec->mc_buf_spec.buf_end |
| - dec->mc_buf_spec.buf_start); |
| if (debug) { |
| pr_err("dec->mc_buf_spec.buf_start %x-%x\n", |
| dec->mc_buf_spec.buf_start, |
| dec->mc_buf_spec.buf_start + |
| dec->mc_buf_spec.buf_size); |
| } |
| avs3_dec_init(dec, cur_buf_info, &dec->mc_buf_spec); |
| #endif |
| if ((buf_alloc_width & buf_alloc_height) == 0) { |
| if (!vdec_is_support_4k() |
| && (buf_alloc_width > 1920 && buf_alloc_height > 1088)) { |
| buf_alloc_width = 1920; |
| buf_alloc_height = 1088; |
| } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { |
| buf_alloc_width = 3840; |
| buf_alloc_height = 2160; |
| } |
| } |
| |
| dec->init_pic_w = buf_alloc_width ? buf_alloc_width : |
| (dec->vavs3_amstream_dec_info.width ? |
| dec->vavs3_amstream_dec_info.width : |
| dec->work_space_buf->max_width); |
| dec->init_pic_h = buf_alloc_height ? buf_alloc_height : |
| (dec->vavs3_amstream_dec_info.height ? |
| dec->vavs3_amstream_dec_info.height : |
| dec->work_space_buf->max_height); |
| |
| pr_info( |
| "init_pic_w %d init_pic_h %d\n", dec->init_pic_w, dec->init_pic_h); |
| |
| #ifndef AVS3_10B_MMU |
| init_buf_list(dec); |
| #else |
| dec->avs3_dec.max_pb_size = max_buf_num + dec->dynamic_buf_margin; |
| if (dec->avs3_dec.max_pb_size > MAX_PB_SIZE) |
| dec->avs3_dec.max_pb_size = MAX_PB_SIZE; |
| #endif |
| //dec->avs3_dec.ref_maxbuffer = MAX_PB_SIZE; //dec->used_buf_num - 1; |
| /*init_pic_list(dec);*/ |
| |
| pts_unstable = ((unsigned long)(dec->vavs3_amstream_dec_info.param) |
| & 0x40) >> 6; |
| |
| if ((debug & AVS3_DBG_SEND_PARAM_WITH_REG) == 0) { |
| dec->rpm_addr = decoder_dma_alloc_coherent(&dec->rpm_mem_handle, |
| RPM_BUF_SIZE, |
| &dec->rpm_phy_addr, "AVS3_RPM_BUF"); |
| if (dec->rpm_addr == NULL) { |
| pr_err("%s: failed to alloc rpm buffer\n", __func__); |
| return -1; |
| } |
| avs3_print(dec, AVS3_DBG_BUFMGR, |
| "rpm_phy_addr %x\n", (u32) dec->rpm_phy_addr); |
| dec->rpm_ptr = dec->rpm_addr; |
| } |
| |
| if (cuva_buf_size > 0) { |
| dec->cuva_size = AUX_BUF_ALIGN(cuva_buf_size); |
| |
| dec->cuva_addr = decoder_dma_alloc_coherent(&dec->cuva_handle, |
| dec->cuva_size, &dec->cuva_phy_addr, "AVS3_CUVA_BUF"); |
| avs3_print(dec, AVS3_DBG_BUFMGR, |
| "%s, cuva_size = %d cuva_phy_addr %x dec->cuva_addr = %px\n", |
| __func__, dec->cuva_size, (u32)dec->cuva_phy_addr, dec->cuva_addr); |
| if (dec->cuva_addr == NULL) { |
| pr_err("%s: failed to alloc cuva buffer\n", __func__); |
| return -1; |
| } |
| } |
| #if (defined DEBUG_UCODE_LOG) || (defined DEBUG_CMD) |
| //if (udebug_flag & 0x8) { |
| dec->ucode_log_addr = decoder_dma_alloc_coherent(&dec->ucode_log_handle, |
| UCODE_LOG_BUF_SIZE, &dec->ucode_log_phy_addr, "AVS3_UCODE_LOG_BUF"); |
| if (dec->ucode_log_addr == NULL) { |
| dec->ucode_log_phy_addr = 0; |
| } |
| pr_info("%s: alloc ucode log buffer %p\n", |
| __func__, dec->ucode_log_addr); |
| //} |
| #endif |
| dec->lmem_addr = decoder_dma_alloc_coherent(&dec->lmem_phy_handle, |
| LMEM_BUF_SIZE, |
| &dec->lmem_phy_addr, "AVS3_LMEM_BUF"); |
| if (dec->lmem_addr == NULL) { |
| pr_err("%s: failed to alloc lmem buffer\n", __func__); |
| return -1; |
| } else |
| avs3_print(dec, AVS3_DBG_BUFMGR, |
| "%s, lmem_phy_addr %x\n", |
| __func__, (u32)dec->lmem_phy_addr); |
| dec->lmem_ptr = dec->lmem_addr; |
| |
| #ifdef AVS3_10B_MMU |
| if (dec->mmu_enable) { |
| dec->frame_mmu_map_addr = decoder_dma_alloc_coherent(&dec->frame_mmu_map_handle, |
| get_frame_mmu_map_size(), |
| &dec->frame_mmu_map_phy_addr, "AVS3_MMU_BUF"); |
| if (dec->frame_mmu_map_addr == NULL) { |
| pr_err("%s: failed to alloc count_buffer\n", __func__); |
| return -1; |
| } |
| memset(dec->frame_mmu_map_addr, 0, get_frame_mmu_map_size()); |
| #ifdef NEW_FB_CODE |
| if (dec->front_back_mode && dec->frame_mmu_map_addr_1 == NULL) { |
| dec->frame_mmu_map_addr_1 = |
| decoder_dma_alloc_coherent(&dec->frame_mmu_map_handle_1, |
| get_frame_mmu_map_size(), |
| &dec->frame_mmu_map_phy_addr_1, "AVS3_MMU_1_BUF"); |
| if (dec->frame_mmu_map_addr_1 == NULL) { |
| pr_err("%s: failed to alloc count_buffer\n", __func__); |
| return -1; |
| } |
| memset(dec->frame_mmu_map_addr_1, 0, get_frame_mmu_map_size()); |
| } |
| #endif |
| } |
| #endif |
| |
| #ifdef AVS3_10B_MMU_DW |
| if (dec->dw_mmu_enable) { |
| dec->dw_frame_mmu_map_addr = decoder_dma_alloc_coherent(&dec->frame_dw_mmu_map_handle, |
| get_frame_mmu_map_size(), |
| &dec->dw_frame_mmu_map_phy_addr, "AVS3_DWMMU_BUF"); |
| if (dec->dw_frame_mmu_map_addr == NULL) { |
| pr_err("%s: failed to alloc count_buffer\n", __func__); |
| return -1; |
| } |
| memset(dec->dw_frame_mmu_map_addr, 0, get_frame_mmu_map_size()); |
| #ifdef NEW_FB_CODE |
| if (dec->front_back_mode) { |
| dec->dw_frame_mmu_map_addr_1 = |
| decoder_dma_alloc_coherent(&dec->frame_dw_mmu_map_handle_1, |
| get_frame_mmu_map_size(), |
| &dec->dw_frame_mmu_map_phy_addr_1, "AVS3_DWMMU_1_BUF"); |
| if (dec->dw_frame_mmu_map_addr_1 == NULL) { |
| pr_err("%s: failed to alloc count_buffer\n", __func__); |
| return -1; |
| } |
| memset(dec->dw_frame_mmu_map_addr_1, 0, get_frame_mmu_map_size()); |
| } |
| #endif |
| } |
| #endif |
| #ifdef NEW_FB_CODE |
| avs3_dec->wait_working_buf = 0; |
| avs3_dec->front_pause_flag = 0; /*multi pictures in one packe*/ |
| if (dec->front_back_mode) { |
| avs3_dec->frontend_decoded_count = 0; |
| avs3_dec->backend_decoded_count = 0; |
| avs3_dec->fb_wr_pos = 0; |
| avs3_dec->fb_rd_pos = 0; |
| init_fb_bufstate(dec); |
| if (fbdebug_flag & 0x4) { |
| copy_loopbufs_ptr(&avs3_dec->init_fr, &avs3_dec->fr); |
| } |
| avs3_print(dec, PRINT_FLAG_VDEC_DETAIL, |
| "copy loopbuf fr to next_bk[fb_wr_pos=%d]\n",avs3_dec->fb_wr_pos); |
| copy_loopbufs_ptr(&avs3_dec->next_bk[avs3_dec->fb_wr_pos], &avs3_dec->fr); |
| } |
| #endif |
| ret = 0; |
| return ret; |
| } |
| |
| /******************************************** |
| * Mailbox command |
| ********************************************/ |
| #define CMD_FINISHED 0 |
| #define CMD_ALLOC_VIEW 1 |
| #define CMD_FRAME_DISPLAY 3 |
| #define CMD_DEBUG 10 |
| |
| #define DECODE_BUFFER_NUM_MAX 32 |
| #define DISPLAY_BUFFER_NUM 6 |
| |
| #define video_domain_addr(adr) (adr&0x7fffffff) |
| #define DECODER_WORK_SPACE_SIZE 0x800000 |
| |
| #define spec2canvas(x) \ |
| (((x)->uv_canvas_index << 16) | \ |
| ((x)->uv_canvas_index << 8) | \ |
| ((x)->y_canvas_index << 0)) |
| |
| static void set_canvas(struct AVS3Decoder_s *dec, |
| struct avs3_frame_s *pic) |
| { |
| int canvas_w = ALIGN(pic->width, 64)/4; |
| int canvas_h = ALIGN(pic->height, 32)/4; |
| int blkmode = mem_map_mode; |
| struct vdec_s *vdec = hw_to_vdec(dec); |
| /*CANVAS_BLKMODE_64X32*/ |
| if (pic->double_write_mode) { |
| canvas_w = pic->width / |
| get_double_write_ratio(pic->double_write_mode); |
| canvas_h = pic->height / |
| get_double_write_ratio(pic->double_write_mode); |
| /*sao_crtl1 aligned with 64*/ |
| canvas_w = ALIGN(canvas_w, 64); |
| canvas_h = ALIGN(canvas_h, 32); |
| |
| if (vdec->parallel_dec == 1) { |
| if (pic->y_canvas_index == -1) |
| pic->y_canvas_index = vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id); |
| if (pic->uv_canvas_index == -1) |
| pic->uv_canvas_index = vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id); |
| } else { |
| pic->y_canvas_index = 128 + pic->index * 2; |
| pic->uv_canvas_index = 128 + pic->index * 2 + 1; |
| } |
| |
| config_cav_lut_ex(pic->y_canvas_index, |
| pic->dw_y_adr, canvas_w, canvas_h, |
| CANVAS_ADDR_NOWRAP, blkmode, 0x7, VDEC_HEVC); |
| config_cav_lut_ex(pic->uv_canvas_index, |
| pic->dw_u_v_adr, canvas_w, canvas_h, |
| CANVAS_ADDR_NOWRAP, blkmode, 0x7, VDEC_HEVC); |
| #ifdef MULTI_INSTANCE_SUPPORT |
| pic->canvas_config[0].phy_addr = pic->dw_y_adr; |
| pic->canvas_config[0].width = canvas_w; |
| pic->canvas_config[0].height = canvas_h; |
| pic->canvas_config[0].block_mode = blkmode; |
| pic->canvas_config[0].endian = 7; |
| |
| pic->canvas_config[1].phy_addr = pic->dw_u_v_adr; |
| pic->canvas_config[1].width = canvas_w; |
| pic->canvas_config[1].height = canvas_h; |
| pic->canvas_config[1].block_mode = blkmode; |
| pic->canvas_config[1].endian = 7; |
| |
| decoder_trace(dec->trace.set_canvas0_addr, pic->canvas_config[0].phy_addr, TRACE_BUFFER); |
| #endif |
| } else { |
| #ifndef AVS3_10B_MMU |
| if (vdec->parallel_dec == 1) { |
| if (pic->y_canvas_index == -1) |
| pic->y_canvas_index = vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id); |
| if (pic->uv_canvas_index == -1) |
| pic->uv_canvas_index = vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id); |
| } else { |
| pic->y_canvas_index = 128 + pic->index; |
| pic->uv_canvas_index = 128 + pic->index; |
| } |
| |
| config_cav_lut_ex(pic->y_canvas_index, |
| pic->mc_y_adr, canvas_w, canvas_h, |
| CANVAS_ADDR_NOWRAP, blkmode, 0x7, VDEC_HEVC); |
| config_cav_lut_ex(pic->uv_canvas_index, |
| pic->mc_u_v_adr,canvas_w, canvas_h, |
| CANVAS_ADDR_NOWRAP, blkmode, 0x7, VDEC_HEVC); |
| |
| decoder_trace(dec->trace.set_canvas0_addr, spec2canvas(pic), TRACE_BUFFER); |
| #endif |
| } |
| } |
| |
| static void set_frame_info(struct AVS3Decoder_s *dec, struct vframe_s *vf) |
| { |
| unsigned int ar = 0; |
| unsigned int pixel_ratio = 0;; |
| |
| vf->duration = dec->frame_dur; |
| vf->duration_pulldown = 0; |
| vf->flag = 0; |
| vf->prop.master_display_colour = dec->vf_dp; |
| if (dec->hdr_flag & HDR_CUVA_MASK) |
| dec->video_signal_type |= 1 << 31; |
| vf->signal_type = dec->video_signal_type; |
| |
| avs3_print(dec, AVS3_DBG_HDR_INFO, |
| "signal_type 0x%x \n", |
| vf->signal_type); |
| |
| pixel_ratio = dec->vavs3_amstream_dec_info.ratio; |
| |
| if (dec->vavs3_ratio == 0) { |
| /* always stretch to 16:9 */ |
| vf->ratio_control |= (0x90 << |
| DISP_RATIO_ASPECT_RATIO_BIT); |
| vf->sar_width = 1; |
| vf->sar_height = 1; |
| } else { |
| switch (pixel_ratio) { |
| case 1: |
| vf->sar_width = 1; |
| vf->sar_height = 1; |
| ar = (vf->height * dec->vavs3_ratio) / vf->width; |
| break; |
| case 2: |
| vf->sar_width = 4; |
| vf->sar_height = 3; |
| ar = (vf->height * 3 * dec->vavs3_ratio) / (vf->width * 4); |
| break; |
| case 3: |
| vf->sar_width = 16; |
| vf->sar_height = 9; |
| ar = (vf->height * 9 * dec->vavs3_ratio) / (vf->width * 16); |
| break; |
| case 4: |
| vf->sar_width = 221; |
| vf->sar_height = 100; |
| ar = (vf->height * 100 * dec->vavs3_ratio) / (vf->width * |
| 221); |
| break; |
| default: |
| vf->sar_width = 1; |
| vf->sar_height = 1; |
| ar = (vf->height * dec->vavs3_ratio) / vf->width; |
| break; |
| } |
| } |
| |
| ar = min_t(u32, ar, DISP_RATIO_ASPECT_RATIO_MAX); |
| vf->ratio_control = (ar << DISP_RATIO_ASPECT_RATIO_BIT); |
| |
| vf->sidebind_type = dec->sidebind_type; |
| vf->sidebind_channel_id = dec->sidebind_channel_id; |
| vf->codec_vfmt = VFORMAT_AVS3; |
| |
| return; |
| } |
| |
| static int vavs3_vf_states(struct vframe_states *states, void *op_arg) |
| { |
| struct AVS3Decoder_s *dec = (struct AVS3Decoder_s *)op_arg; |
| |
| states->vf_pool_size = VF_POOL_SIZE; |
| states->buf_free_num = kfifo_len(&dec->newframe_q); |
| states->buf_avail_num = kfifo_len(&dec->display_q); |
| |
| if (step == 2) |
| states->buf_avail_num = 0; |
| return 0; |
| } |
| |
| static struct vframe_s *vavs3_vf_peek(void *op_arg) |
| { |
| struct vframe_s *vf; |
| struct AVS3Decoder_s *dec = (struct AVS3Decoder_s *)op_arg; |
| if (step == 2) |
| return NULL; |
| |
| if (force_disp_pic_index & 0x100) { |
| if (force_disp_pic_index & 0x200) |
| return NULL; |
| return &dec->vframe_dummy; |
| } |
| |
| if (kfifo_len(&dec->display_q) > VF_POOL_SIZE) { |
| avs3_print(dec, AVS3_DBG_BUFMGR, |
| "kfifo len:%d invalid, peek error\n", |
| kfifo_len(&dec->display_q)); |
| return NULL; |
| } |
| #ifdef NEW_FB_CODE |
| if (dec->front_back_mode) { |
| struct vframe_s *vf_tmp; |
| if (kfifo_peek(&dec->display_q, &vf_tmp) && vf_tmp) { |
| uint8_t index = vf_tmp->index & 0xff; |
| struct avs3_frame_s *pic = get_pic_by_index(dec, index); |
| if (!pic->back_done_mark) { |
| return NULL; |
| } |
| } else |
| return NULL; |
| } |
| #endif |
| |
| if (kfifo_peek(&dec->display_q, &vf)) { |
| return vf; |
| } |
| |
| return NULL; |
| } |
| |
| static struct avs3_frame_s *get_pic_by_index( |
| struct AVS3Decoder_s *dec, int index) |
| { |
| int i; |
| struct avs3_frame_s *pic = NULL; |
| for (i = 0; i < dec->avs3_dec.max_pb_size; i++) { |
| if (dec->avs3_dec.pic_pool[i].buf_cfg.index == index) |
| pic = &dec->avs3_dec.pic_pool[i].buf_cfg; |
| } |
| return pic; |
| } |
| |
| static void update_vf_memhandle(struct AVS3Decoder_s *dec, |
| struct vframe_s *vf, struct avs3_frame_s *pic) |
| { |
| vf->mem_handle = NULL; |
| vf->mem_handle_1 = NULL; |
| vf->mem_head_handle = NULL; |
| vf->mem_dw_handle = NULL; |
| |
| #ifdef AVS3_10B_MMU |
| if (vf->type & VIDTYPE_SCATTER) { |
| #ifdef AVS3_10B_MMU_DW |
| if (pic->double_write_mode & 0x20) { |
| vf->mem_handle = |
| decoder_mmu_box_get_mem_handle( |
| dec->dw_mmu_box, pic->index); |
| if (dec->front_back_mode) |
| vf->mem_handle_1 = decoder_mmu_box_get_mem_handle(dec->dw_mmu_box_1, pic->index); |
| vf->mem_head_handle = |
| decoder_bmmu_box_get_mem_handle( |
| dec->bmmu_box, |
| HEADER_BUFFER_IDX(pic->BUF_index)); |
| vf->mem_dw_handle = NULL; |
| } else |
| #endif |
| { |
| vf->mem_handle = decoder_mmu_box_get_mem_handle( |
| dec->mmu_box, |
| pic->index); |
| if (dec->front_back_mode) |
| vf->mem_handle_1 = decoder_mmu_box_get_mem_handle(dec->mmu_box_1, pic->index); |
| vf->mem_head_handle = decoder_bmmu_box_get_mem_handle( |
| dec->bmmu_box, |
| HEADER_BUFFER_IDX(pic->index)); |
| } |
| } else { |
| vf->mem_handle = decoder_bmmu_box_get_mem_handle( |
| dec->bmmu_box, |
| VF_BUFFER_IDX(pic->index)); |
| vf->mem_head_handle = decoder_bmmu_box_get_mem_handle( |
| dec->bmmu_box, |
| HEADER_BUFFER_IDX(pic->index)); |
| } |
| #else |
| vf->mem_handle = decoder_bmmu_box_get_mem_handle( |
| dec->bmmu_box, |
| VF_BUFFER_IDX(pic->index)); |
| #endif |
| } |
| |
| static struct vframe_s *vavs3_vf_get(void *op_arg) |
| { |
| struct vframe_s *vf; |
| struct AVS3Decoder_s *dec = (struct AVS3Decoder_s *)op_arg; |
| if (step == 2) |
| return NULL; |
| else if (step == 1) |
| step = 2; |
| |
| if (force_disp_pic_index & 0x100) { |
| int idx = force_disp_pic_index & 0xff; |
| struct avs3_frame_s *pic = NULL; |
| if (idx >= 0 |
| && idx < dec->avs3_dec.max_pb_size) |
| pic = get_pic_by_index(dec, idx); |
| if (pic == NULL) |
| return NULL; |
| if (force_disp_pic_index & 0x200) |
| return NULL; |
| |
| vf = &dec->vframe_dummy; |
| |
| set_vframe(dec, vf, pic, 1); |
| |
| force_disp_pic_index |= 0x200; |
| return vf; |
| } |
| |
| #ifdef NEW_FB_CODE |
| if (dec->front_back_mode) { |
| if (kfifo_peek(&dec->display_q, &vf) && vf) { |
| uint8_t index = vf->index & 0xff; |
| struct avs3_frame_s *pic = get_pic_by_index(dec, index); |
| if (!pic->back_done_mark) { |
| return NULL; |
| } |
| } else |
| return NULL; |
| } |
| #endif |
| |
| if (kfifo_get(&dec->display_q, &vf)) { |
| uint8_t index = vf->index & 0xff; |
| struct vdec_s *vdec = hw_to_vdec(dec); |
| |
| decoder_trace(dec->trace.vf_get_name, (long)vf, TRACE_BUFFER); |
| decoder_trace(dec->trace.disp_q_name, kfifo_len(&dec->display_q), TRACE_BUFFER); |
| #ifdef MULTI_INSTANCE_SUPPORT |
| decoder_trace(dec->trace.set_canvas0_addr, vf->canvas0_config[0].phy_addr, TRACE_BUFFER); |
| #else |
| decoder_trace(dec->trace.get_canvas0_addr, vf->canvas0Addr, TRACE_BUFFER); |
| #endif |
| |
| if (index < dec->avs3_dec.max_pb_size) { |
| struct avs3_frame_s *pic = get_pic_by_index(dec, index); |
| if (pic == NULL && |
| (debug & AVS3_DBG_PIC_LEAK)) { |
| int i; |
| avs3_print(dec, 0, |
| "%s error index 0x%x pic not exist\n", |
| __func__, index); |
| print_pic_pool(&dec->avs3_dec, ""); |
| for (i = 0; i < 10; i++) { |
| pic = get_pic_by_index(dec, index); |
| pr_info("pic = %p\n", pic); |
| } |
| |
| if (debug & AVS3_DBG_PIC_LEAK) |
| debug |= AVS3_DBG_PIC_LEAK_WAIT; |
| return NULL; |
| } |
| |
| vf->vf_ud_param.magic_code = UD_MAGIC_CODE; |
| vf->vf_ud_param.ud_param.buf_len = 0; |
| vf->vf_ud_param.ud_param.pbuf_addr = NULL; |
| vf->vf_ud_param.ud_param.instance_id = vdec->afd_video_id; |
| |
| vf->vf_ud_param.ud_param.meta_info.duration = vf->duration; |
| vf->vf_ud_param.ud_param.meta_info.flags = (VFORMAT_AVS3 << 3); |
| vf->vf_ud_param.ud_param.meta_info.vpts = vf->pts; |
| if (vf->pts) |
| vf->vf_ud_param.ud_param.meta_info.vpts_valid = 1; |
| |
| vf->omx_index = dec->vf_get_count; |
| dec->vf_get_count++; |
| if (pic) { |
| if (dec->front_back_mode == 1) { |
| update_vf_memhandle(dec, vf, pic); |
| decoder_do_frame_check(hw_to_vdec(dec), vf); |
| } |
| avs3_print(dec, AVS3_DBG_BUFMGR, |
| "%s vf %p pic %p index 0x%x getcount %d type 0x%x w/h/depth %d/%d/0x%x, compHeadAddr 0x%08x, pts %d, %lld\n", |
| __func__, vf, pic, index, |
| //pic->imgtr_fwRefDistance_bak, |
| dec->vf_get_count, |
| vf->type, |
| vf->width, vf->height, |
| vf->bitdepth, |
| vf->compHeadAddr, |
| vf->pts, |
| vf->pts_us64); |
| } |
| |
| if (pic && (!(pic->error_mark) || !(error_handle_policy & 0x4))) |
| return vf; |
| |
| dec->vf_get_count--; |
| dec->vf_pre_count--; |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, |
| "%s:get error pic from fifo\n", __func__); |
| vavs3_vf_put(vf, dec); |
| return NULL; |
| } |
| } |
| return NULL; |
| } |
| |
| static void vavs3_vf_put(struct vframe_s *vf, void *op_arg) |
| { |
| struct AVS3Decoder_s *dec = (struct AVS3Decoder_s *)op_arg; |
| #ifdef MULTI_INSTANCE_SUPPORT |
| struct vdec_s *vdec = hw_to_vdec(dec); |
| #endif |
| uint8_t index; |
| |
| if (vf == (&dec->vframe_dummy)) |
| return; |
| |
| if (!vf) |
| return; |
| |
| index = vf->index & 0xff; |
| |
| decoder_trace(dec->trace.vf_put_name, (long)vf, TRACE_BUFFER); |
| #ifdef MULTI_INSTANCE_SUPPORT |
| decoder_trace(dec->trace.put_canvas0_addr, vf->canvas0_config[0].phy_addr, TRACE_BUFFER); |
| #else |
| decoder_trace(dec->trace.put_canvas0_addr, vf->canvas0Addr, TRACE_BUFFER); |
| #endif |
| |
| kfifo_put(&dec->newframe_q, (const struct vframe_s *)vf); |
| decoder_trace(dec->trace.new_q_name, kfifo_len(&dec->newframe_q), TRACE_BUFFER); |
| |
| if (index < dec->avs3_dec.max_pb_size) { |
| unsigned long flags; |
| struct avs3_frame_s *pic; |
| |
| lock_buffer(dec, flags); |
| pic = get_pic_by_index(dec, index); |
| if (pic && pic->vf_ref > 0) { |
| pic->vf_ref--; |
| } else { |
| if (pic) |
| avs3_print(dec, 0, |
| "%s, error pic (index %d) vf_ref is %d\n", |
| __func__, index, pic->vf_ref); |
| else |
| avs3_print(dec, 0, |
| "%s, error pic (index %d) is NULL\n", |
| __func__, index); |
| } |
| |
| if (pic && (!(pic->error_mark) || !(error_handle_policy & 0x4))) |
| dec->vf_put_count++; |
| |
| avs3_print(dec, AVS3_DBG_BUFMGR, |
| "%s vf %p pic %p index 0x%x putcount %d\n", |
| __func__, vf, pic, vf->index & 0xff, dec->vf_put_count); |
| |
| if (dec->wait_buf) |
| WRITE_VREG(dec->ASSIST_MBOX0_IRQ_REG, 0x1); |
| dec->last_put_idx = index; |
| dec->new_frame_displayed++; |
| unlock_buffer(dec, flags); |
| } |
| #ifdef MULTI_INSTANCE_SUPPORT |
| vdec_up(vdec); |
| #endif |
| } |
| |
| static int vavs3_event_cb(int type, void *data, void *private_data) |
| { |
| struct AVS3Decoder_s *dec = (struct AVS3Decoder_s *)private_data; |
| |
| if (type & VFRAME_EVENT_RECEIVER_REQ_STATE) { |
| struct provider_state_req_s *req = |
| (struct provider_state_req_s *)data; |
| if (req->req_type == REQ_STATE_SECURE) |
| req->req_result[0] = vdec_secure(hw_to_vdec(dec)); |
| else |
| req->req_result[0] = 0xffffffff; |
| } else if (type & VFRAME_EVENT_RECEIVER_GET_AUX_DATA) { |
| struct provider_aux_req_s *req = |
| (struct provider_aux_req_s *)data; |
| unsigned char index; |
| unsigned long flags; |
| struct avs3_frame_s *pic; |
| |
| if (!req->vf) { |
| req->aux_size = dec->vf_put_count; |
| return 0; |
| } |
| lock_buffer(dec, flags); |
| index = req->vf->index & 0xff; |
| req->aux_buf = NULL; |
| req->aux_size = 0; |
| req->format = VFORMAT_AVS3; |
| if (index < dec->avs3_dec.max_pb_size) { |
| pic = get_pic_by_index(dec, index); |
| req->aux_buf = pic->cuva_data_buf; |
| req->aux_size = pic->cuva_data_size; |
| } |
| unlock_buffer(dec, flags); |
| |
| avs3_print(dec, PRINT_FLAG_VDEC_STATUS, |
| "%s pic 0x%p index %d =>size %d\n", |
| __func__, pic, index, req->aux_size); |
| } |
| |
| return 0; |
| } |
| |
| /* |
| static struct avs3_frame_s *get_disp_pic(struct AVS3Decoder_s *dec) |
| { |
| struct avs3_decoder *avs3_dec = &dec->avs3_dec; |
| struct avs3_frame_s *pic = NULL; |
| int32_t j; |
| int32_t pre_disp_count_min = 0x7fffffff; |
| for (j = 0; j < avs3_dec->ref_maxbuffer; j++) { |
| if (avs3_dec->fref[j]->to_prepare_disp && |
| avs3_dec->fref[j]->to_prepare_disp < |
| pre_disp_count_min) { |
| pre_disp_count_min = |
| avs3_dec->fref[j]->to_prepare_disp; |
| pic = avs3_dec->fref[j]; |
| } |
| } |
| if (pic) |
| pic->to_prepare_disp = 0; |
| |
| return pic; |
| |
| } |
| */ |
| |
| static void fill_frame_info(struct AVS3Decoder_s *dec, |
| struct avs3_frame_s *pic, unsigned int framesize, unsigned int pts) |
| { |
| struct vframe_qos_s *vframe_qos = &dec->vframe_qos; |
| |
| if (pic->slice_type == I_IMG) |
| vframe_qos->type = 1; |
| else if (pic->slice_type == P_IMG) |
| vframe_qos->type = 2; |
| else if (pic->slice_type == B_IMG) |
| vframe_qos->type = 3; |
| /* |
| #define SHOW_QOS_INFO |
| */ |
| if (input_frame_based(hw_to_vdec(dec))) |
| vframe_qos->size = pic->frame_size; |
| else |
| vframe_qos->size = framesize; |
| vframe_qos->pts = pts; |
| #ifdef SHOW_QOS_INFO |
| avs3_print(dec, 0, "slice:%d\n", pic->slice_type); |
| #endif |
| |
| vframe_qos->max_mv = pic->max_mv; |
| vframe_qos->avg_mv = pic->avg_mv; |
| vframe_qos->min_mv = pic->min_mv; |
| #ifdef SHOW_QOS_INFO |
| avs3_print(dec, 0, "mv: max:%d, avg:%d, min:%d\n", |
| vframe_qos->max_mv, |
| vframe_qos->avg_mv, |
| vframe_qos->min_mv); |
| #endif |
| |
| vframe_qos->max_qp = pic->max_qp; |
| vframe_qos->avg_qp = pic->avg_qp; |
| vframe_qos->min_qp = pic->min_qp; |
| #ifdef SHOW_QOS_INFO |
| avs3_print(dec, 0, "qp: max:%d, avg:%d, min:%d\n", |
| vframe_qos->max_qp, |
| vframe_qos->avg_qp, |
| vframe_qos->min_qp); |
| #endif |
| |
| vframe_qos->max_skip = pic->max_skip; |
| vframe_qos->avg_skip = pic->avg_skip; |
| vframe_qos->min_skip = pic->min_skip; |
| #ifdef SHOW_QOS_INFO |
| avs3_print(dec, 0, "skip: max:%d, avg:%d, min:%d\n", |
| vframe_qos->max_skip, |
| vframe_qos->avg_skip, |
| vframe_qos->min_skip); |
| #endif |
| |
| vframe_qos->num++; |
| |
| } |
| |
| static void set_vframe(struct AVS3Decoder_s *dec, |
| struct vframe_s *vf, struct avs3_frame_s *pic, u8 dummy) |
| { |
| int stream_offset; |
| unsigned int frame_size = 0; |
| int pts_discontinue; |
| struct vdec_s *vdec = hw_to_vdec(dec); |
| stream_offset = pic->stream_offset; |
| avs3_print(dec, AVS3_DBG_BUFMGR, |
| "%s index = %d\r\n", |
| __func__, pic->index); |
| |
| if (pic->double_write_mode && (pic->double_write_mode & 0x20) == 0) |
| set_canvas(dec, pic); |
| |
| display_frame_count[dec->index]++; |
| |
| if (!dummy) { |
| #ifdef MULTI_INSTANCE_SUPPORT |
| if (vdec_frame_based(vdec)) { |
| vf->pts = pic->pts; |
| vf->pts_us64 = pic->pts64; |
| } else { |
| #endif |
| if ((vdec->vbuf.no_parser == 0) || (vdec->vbuf.use_ptsserv)) { |
| /* if (pts_lookup_offset(PTS_TYPE_VIDEO, |
| stream_offset, &vf->pts, 0) != 0) { */ |
| if (pts_lookup_offset_us64 |
| (PTS_TYPE_VIDEO, stream_offset, |
| &vf->pts, &frame_size, 0, |
| &vf->pts_us64) != 0) { |
| #ifdef DEBUG_PTS |
| dec->pts_missed++; |
| #endif |
| vf->pts = 0; |
| vf->pts_us64 = 0; |
| } |
| } |
| } |
| #ifdef DEBUG_PTS |
| else |
| dec->pts_hit++; |
| #endif |
| if (pts_unstable) |
| dec->pts_mode = PTS_NONE_REF_USE_DURATION; |
| |
| fill_frame_info(dec, pic, frame_size, vf->pts); |
| |
| if ((dec->pts_mode == PTS_NORMAL) && (vf->pts != 0) |
| && dec->get_frame_dur) { |
| int pts_diff = (int)vf->pts - dec->last_lookup_pts; |
| |
| if (pts_diff < 0) { |
| dec->pts_mode_switching_count++; |
| dec->pts_mode_recovery_count = 0; |
| |
| if (dec->pts_mode_switching_count >= |
| PTS_MODE_SWITCHING_THRESHOLD) { |
| dec->pts_mode = |
| PTS_NONE_REF_USE_DURATION; |
| pr_info |
| ("HEVC: switch to n_d mode.\n"); |
| } |
| |
| } else { |
| int p = PTS_MODE_SWITCHING_RECOVERY_THRESHOLD; |
| dec->pts_mode_recovery_count++; |
| if (dec->pts_mode_recovery_count > p) { |
| dec->pts_mode_switching_count = 0; |
| dec->pts_mode_recovery_count = 0; |
| } |
| } |
| } |
| |
| pts_discontinue = |
| (abs(dec->last_pts - vf->pts) >= |
| tsync_vpts_discontinuity_margin()); |
| |
| if (vf->pts != 0) |
| dec->last_lookup_pts = vf->pts; |
| |
| if ((dec->pts_mode == PTS_NONE_REF_USE_DURATION) |
| && ((pic->slice_type != I_IMG) || (!pts_discontinue && |
| !first_pts_checkin_complete(PTS_TYPE_AUDIO)))) |
| vf->pts = dec->last_pts + DUR2PTS(dec->frame_dur); |
| dec->last_pts = vf->pts; |
| |
| if (vf->pts_us64 != 0) |
| dec->last_lookup_pts_us64 = vf->pts_us64; |
| |
| if ((dec->pts_mode == PTS_NONE_REF_USE_DURATION) |
| && ((pic->slice_type != I_IMG) || (!pts_discontinue && |
| !first_pts_checkin_complete(PTS_TYPE_AUDIO)))) { |
| vf->pts_us64 = |
| dec->last_pts_us64 + |
| (DUR2PTS(dec->frame_dur) * 100 / 9); |
| } |
| |
| dec->last_pts_us64 = vf->pts_us64; |
| } |
| |
| vf->index = 0xff00 | pic->index; |
| |
| if (pic->double_write_mode & 0x10) { |
| /* double write only */ |
| vf->compBodyAddr = 0; |
| vf->compHeadAddr = 0; |
| } else { |
| #ifdef AVS3_10B_MMU |
| vf->compBodyAddr = 0; |
| vf->compHeadAddr = pic->header_adr; |
| #ifdef AVS3_10B_MMU_DW |
| vf->dwBodyAddr = 0; |
| vf->dwHeadAddr = 0; |
| if (pic->double_write_mode & 0x20) { |
| u32 mode = pic->double_write_mode & 0xf; |
| if (mode == 5 || mode == 3) |
| vf->dwHeadAddr = pic->dw_header_adr; |
| else if ((mode == 1 || mode == 2 || mode == 4) |
| && ((debug & AVS3_DBG_OUT_PTS) == 0)) { |
| vf->compHeadAddr = pic->dw_header_adr; |
| pr_info("Use dw mmu for display\n"); |
| } |
| } |
| #endif |
| |
| #else |
| vf->compBodyAddr = pic->mc_y_adr; /*body adr*/ |
| vf->compHeadAddr = pic->mc_y_adr + pic->comp_body_size; |
| #endif |
| } |
| if (pic->double_write_mode && |
| ((pic->double_write_mode & 0x20) == 0)) { |
| vf->type = VIDTYPE_PROGRESSIVE | |
| VIDTYPE_VIU_FIELD; |
| vf->type |= VIDTYPE_VIU_NV21; |
| if (pic->double_write_mode == 3) { |
| vf->type |= VIDTYPE_COMPRESS; |
| #ifdef AVS3_10B_MMU |
| vf->type |= VIDTYPE_SCATTER; |
| #endif |
| } |
| #ifdef MULTI_INSTANCE_SUPPORT |
| if (dec->m_ins_flag) { |
| vf->canvas0Addr = vf->canvas1Addr = -1; |
| vf->plane_num = 2; |
| vf->canvas0_config[0] = |
| pic->canvas_config[0]; |
| vf->canvas0_config[1] = |
| pic->canvas_config[1]; |
| |
| vf->canvas1_config[0] = |
| pic->canvas_config[0]; |
| vf->canvas1_config[1] = |
| pic->canvas_config[1]; |
| |
| } else |
| #endif |
| vf->canvas0Addr = vf->canvas1Addr = |
| spec2canvas(pic); |
| } else { |
| vf->canvas0Addr = vf->canvas1Addr = 0; |
| vf->type = VIDTYPE_COMPRESS | VIDTYPE_VIU_FIELD; |
| #ifdef AVS3_10B_MMU |
| vf->type |= VIDTYPE_SCATTER; |
| #endif |
| } |
| |
| switch (pic->depth) { |
| case AVS3_BITS_8: |
| vf->bitdepth = BITDEPTH_Y8 | |
| BITDEPTH_U8 | BITDEPTH_V8; |
| break; |
| case AVS3_BITS_10: |
| case AVS3_BITS_12: |
| vf->bitdepth = BITDEPTH_Y10 | |
| BITDEPTH_U10 | BITDEPTH_V10; |
| break; |
| default: |
| vf->bitdepth = BITDEPTH_Y10 | |
| BITDEPTH_U10 | BITDEPTH_V10; |
| break; |
| } |
| if ((vf->type & VIDTYPE_COMPRESS) == 0) |
| vf->bitdepth = |
| BITDEPTH_Y8 | BITDEPTH_U8 | BITDEPTH_V8; |
| if (pic->depth == AVS3_BITS_8) |
| vf->bitdepth |= BITDEPTH_SAVING_MODE; |
| |
| set_frame_info(dec, vf); |
| /* if ((vf->width!=pic->width)| |
| (vf->height!=pic->height)) */ |
| /* pr_info("aaa: %d/%d, %d/%d\n", |
| vf->width,vf->height, pic->width, |
| pic->height); */ |
| vf->width = pic->width / |
| get_double_write_ratio(pic->double_write_mode); |
| vf->height = pic->height / |
| get_double_write_ratio(pic->double_write_mode); |
| if (force_w_h != 0) { |
| vf->width = (force_w_h >> 16) & 0xffff; |
| vf->height = force_w_h & 0xffff; |
| } |
| if ((pic->double_write_mode & 0x20) && |
| ((pic->double_write_mode & 0xf) == 2 || |
| (pic->double_write_mode & 0xf) == 4)) { |
| vf->compWidth = pic->width / |
| get_double_write_ratio( |
| pic->double_write_mode & 0xf); |
| vf->compHeight = pic->height / |
| get_double_write_ratio( |
| pic->double_write_mode & 0xf); |
| } else { |
| vf->compWidth = pic->width; |
| vf->compHeight = pic->height; |
| } |
| if (force_fps & 0x100) { |
| u32 rate = force_fps & 0xff; |
| if (rate) |
| vf->duration = 96000/rate; |
| else |
| vf->duration = 0; |
| } |
| |
| if (dec->front_back_mode != 1) |
| update_vf_memhandle(dec, vf, pic); |
| if (!vdec->vbuf.use_ptsserv && vdec_stream_based(vdec)) { |
| /* offset for tsplayer pts lookup */ |
| u64 frame_type = 0; |
| if (pic->slice_type == I_IMG) |
| frame_type = KEYFRAME_FLAG; |
| else if (pic->slice_type == P_IMG) |
| frame_type = PFRAME_FLAG; |
| else |
| frame_type = BFRAME_FLAG; |
| vf->pts_us64 = (((u64)vf->duration << 32 | (frame_type << 62)) & 0xffffffff00000000) |
| | pic->stream_offset; |
| vf->pts = 0; |
| } |
| avs3_print(dec, AVS3_DBG_OUT_PTS, |
| "avs3 dec out pts: vf->pts=%d, vf->pts_us64 = %lld slice_type %d, duration %d\n", |
| vf->pts, vf->pts_us64, pic->slice_type, vf->duration); |
| |
| if (!dummy) { |
| pic->vf_ref = 1; |
| } |
| dec->vf_pre_count++; |
| } |
| |
| static inline void dec_update_gvs(struct AVS3Decoder_s *dec) |
| { |
| if (dec->gvs->frame_height != dec->frame_height) { |
| dec->gvs->frame_width = dec->frame_width; |
| dec->gvs->frame_height = dec->frame_height; |
| } |
| /*if (dec->gvs->frame_dur != dec->frame_dur) { |
| dec->gvs->frame_dur = dec->frame_dur; |
| if (dec->frame_dur != 0) |
| dec->gvs->frame_rate = ((96000 * 10 / dec->frame_dur) % 10) < 5 ? |
| 96000 / dec->frame_dur : (96000 / dec->frame_dur +1); |
| else |
| dec->gvs->frame_rate = -1; |
| }*/ |
| dec->gvs->status = dec->stat | dec->fatal_error; |
| } |
| |
| static int avs3_prepare_display_buf(struct AVS3Decoder_s *dec) |
| { |
| #ifndef NO_DISPLAY |
| struct vframe_s *vf = NULL; |
| /*unsigned short slice_type;*/ |
| struct avs3_frame_s *pic; |
| struct vdec_s *pvdec = hw_to_vdec(dec); |
| |
| while (1) { |
| COM_PIC *com_pic = dec_pull_frm(&dec->avs3_dec.ctx, 0); |
| |
| if (com_pic == NULL) |
| break; |
| pic = &com_pic->buf_cfg; |
| if (force_disp_pic_index & 0x100) { |
| /*recycle directly*/ |
| continue; |
| } |
| |
| if (pic->error_mark && (error_handle_policy & 0x4)) { |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, |
| "%s: error pic, skip\n", __func__); |
| continue; |
| } |
| |
| if (dec->start_decoding_flag != 0) { |
| if (dec->skip_PB_before_I && |
| pic->slice_type != I_IMG) { |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, |
| "!!!slice type %d (not I) skip\n", |
| 0, pic->slice_type); |
| continue; |
| } |
| dec->skip_PB_before_I = 0; |
| } |
| |
| if (kfifo_get(&dec->newframe_q, &vf) == 0) { |
| pr_info("fatal error, no available buffer slot."); |
| return -1; |
| } |
| |
| if (vf) { |
| struct vdec_info tmp4x; |
| int stream_offset = pic->stream_offset; |
| set_vframe(dec, vf, pic, 0); |
| if (dec->front_back_mode != 1) |
| decoder_do_frame_check(pvdec, vf); |
| vdec_vframe_ready(pvdec, vf); |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, |
| "%s: pic %p stream_offset 0x%x\n", |
| __func__, com_pic, pic->stream_offset); |
| |
| kfifo_put(&dec->display_q, (const struct vframe_s *)vf); |
| decoder_trace(dec->trace.pts_name, vf->pts, TRACE_BUFFER); |
| decoder_trace(dec->trace.new_q_name, kfifo_len(&dec->newframe_q), TRACE_BUFFER); |
| decoder_trace(dec->trace.disp_q_name, kfifo_len(&dec->display_q), TRACE_BUFFER); |
| |
| dec_update_gvs(dec); |
| /*count info*/ |
| vdec_count_info(dec->gvs, 0, stream_offset); |
| if (stream_offset) { |
| if (pic->slice_type == I_IMG) { |
| dec->gvs->i_decoded_frames++; |
| } else if (pic->slice_type == P_IMG) { |
| dec->gvs->p_decoded_frames++; |
| } else if (pic->slice_type == B_IMG) { |
| dec->gvs->b_decoded_frames++; |
| } |
| } |
| memcpy(&tmp4x, dec->gvs, sizeof(struct vdec_info)); |
| tmp4x.bit_depth_luma = bit_depth_luma; |
| tmp4x.bit_depth_chroma = bit_depth_chroma; |
| tmp4x.double_write_mode = pic->double_write_mode; |
| vdec_fill_vdec_frame(pvdec, &dec->vframe_qos, &tmp4x, vf, pic->hw_decode_time); |
| pvdec->vdec_fps_detec(pvdec->id); |
| if (without_display_mode == 0) { |
| if (dec->front_back_mode != 1) |
| vf_notify_receiver(dec->provider_name, |
| VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); |
| } else |
| vavs3_vf_put(vavs3_vf_get(dec), dec); |
| } |
| } |
| /*!NO_DISPLAY*/ |
| #endif |
| return 0; |
| } |
| |
| static void get_rpm_param(union param_u *params) |
| { |
| int i; |
| unsigned int data32; |
| if (debug & AVS3_DBG_BUFMGR) |
| pr_info("enter %s\r\n", __func__); |
| for (i = 0; i < (RPM_END - RPM_BEGIN); i++) { |
| do { |
| data32 = READ_VREG(RPM_CMD_REG); |
| /*pr_info("%x\n", data32);*/ |
| } while ((data32 & 0x10000) == 0); |
| params->l.data[i] = data32&0xffff; |
| /*pr_info("%x\n", data32);*/ |
| WRITE_VREG(RPM_CMD_REG, 0); |
| } |
| if (debug & AVS3_DBG_BUFMGR) |
| pr_info("leave %s\r\n", __func__); |
| } |
| static void debug_buffer_mgr_more(struct AVS3Decoder_s *dec) |
| { |
| int i; |
| if (!(debug & AVS3_DBG_BUFMGR_MORE)) |
| return; |
| //avs3_print(dec, 0, "avs3_param: (%d)\n", dec->avs3_dec.img.number); |
| pr_info("avs3_param: (%d)\n", dec->avs3_dec.img.number); |
| for (i = 0; i < (RPM_END-RPM_BEGIN); i++) { |
| avs3_print_cont(dec, 0, "%04x ", dec->avs3_dec.param.l.data[i]); |
| if (((i + 1) & 0xf) == 0) { |
| avs3_print_cont(dec, 0, "\n"); |
| avs3_print_flush(dec); |
| } |
| } |
| avs3_print(dec, 0, "\n"); |
| } |
| |
| #ifdef AVS3_10B_MMU |
| static void avs3_recycle_mmu_buf_tail(struct AVS3Decoder_s *dec) |
| { |
| if (dec->cur_fb_idx_mmu != INVALID_IDX) { |
| u32 used_4k_num = |
| (READ_VREG(HEVC_SAO_MMU_STATUS) >> 16); |
| if (dec->m_ins_flag) |
| hevc_mmu_dma_check(hw_to_vdec(dec)); |
| decoder_mmu_box_free_idx_tail(dec->mmu_box, |
| dec->cur_fb_idx_mmu, used_4k_num); |
| |
| avs3_print(dec, AVS3_DBG_BUFMGR_MORE, |
| "%s decoder_mmu_box_free_idx_tail index=%d used_4k_num %d\n", |
| __func__, dec->cur_fb_idx_mmu, used_4k_num); |
| |
| if (dec->dw_mmu_enable) { |
| used_4k_num = READ_VREG(HEVC_SAO_MMU_STATUS2) >> 16; |
| avs3_print(dec, AVS3_DBG_BUFMGR_MORE, |
| "%s DW decoder_mmu_box_free_idx_tail index=%d used_4k_num %d\n", |
| __func__, dec->cur_fb_idx_mmu, used_4k_num); |
| |
| decoder_mmu_box_free_idx_tail( |
| dec->dw_mmu_box, |
| dec->cur_fb_idx_mmu, |
| used_4k_num); |
| } |
| |
| dec->cur_fb_idx_mmu = INVALID_IDX; |
| } |
| } |
| |
| static void avs3_recycle_mmu_buf(struct AVS3Decoder_s *dec) |
| { |
| if (dec->cur_fb_idx_mmu != INVALID_IDX) { |
| decoder_mmu_box_free_idx(dec->mmu_box, |
| dec->cur_fb_idx_mmu); |
| |
| if (dec->front_back_mode) |
| decoder_mmu_box_free_idx(dec->mmu_box_1, |
| dec->cur_fb_idx_mmu); |
| |
| avs3_print(dec, AVS3_DBG_BUFMGR_MORE, |
| "%s decoder_mmu_box_free_idx index=%d\n", |
| __func__, dec->cur_fb_idx_mmu); |
| |
| if (dec->dw_mmu_enable) { |
| decoder_mmu_box_free_idx(dec->dw_mmu_box, |
| dec->cur_fb_idx_mmu); |
| |
| if (dec->front_back_mode) |
| decoder_mmu_box_free_idx(dec->dw_mmu_box_1, |
| dec->cur_fb_idx_mmu); |
| |
| avs3_print(dec, AVS3_DBG_BUFMGR_MORE, |
| "%s DW decoder_mmu_box_free_idx index=%d\n", |
| __func__, dec->cur_fb_idx_mmu); |
| } |
| dec->cur_fb_idx_mmu = INVALID_IDX; |
| } |
| } |
| #endif |
| |
| static void dec_again_process(struct AVS3Decoder_s *dec) |
| { |
| #ifdef NEW_FB_CODE |
| if (dec->front_back_mode == 1) |
| amhevc_stop_f(); |
| else |
| #endif |
| amhevc_stop(); |
| dec->dec_result = DEC_RESULT_AGAIN; |
| if (dec->process_state == |
| PROC_STATE_DECODING) { |
| dec->process_state = |
| PROC_STATE_DECODE_AGAIN; |
| } else if (dec->process_state == |
| PROC_STATE_HEAD_DONE) { |
| dec->process_state = |
| PROC_STATE_HEAD_AGAIN; |
| } |
| dec->next_again_flag = 1; |
| reset_process_time(dec); |
| |
| vdec_schedule_work(&dec->work); |
| } |
| /* |
| static uint32_t log2i(uint32_t val) |
| { |
| uint32_t ret = -1; |
| while (val != 0) { |
| val >>= 1; |
| ret++; |
| } |
| return ret; |
| } |
| */ |
| static void check_pic_error(struct AVS3Decoder_s *dec, |
| struct avs3_frame_s *pic) |
| { |
| #ifndef PXP_DEBUG |
| if (dec->front_back_mode == 3 || |
| (debug & AVS3_DBG_DIS_LOC_ERROR_PROC)) |
| return; |
| if (pic->decoded_lcu == 0) { |
| pic->decoded_lcu = |
| (READ_VREG(HEVC_PARSER_LCU_START) |
| & 0xffffff) + 1; |
| } |
| if (pic->decoded_lcu != dec->avs3_dec.lcu_total) { |
| avs3_print(dec, AVS3_DBG_BUFMGR, |
| "%s error pic(index %d) decoded lcu %d (total %d)\n", |
| __func__, pic->index, |
| pic->decoded_lcu, dec->avs3_dec.lcu_total); |
| pic->error_mark = 1; |
| } else { |
| avs3_print(dec, AVS3_DBG_BUFMGR_MORE, |
| "%s pic(index %d) decoded lcu %d (total %d)\n", |
| __func__, pic->index, |
| pic->decoded_lcu, dec->avs3_dec.lcu_total); |
| |
| } |
| #endif |
| } |
| static void update_decoded_pic(struct AVS3Decoder_s *dec) |
| { |
| struct avs3_frame_s *pic = dec->avs3_dec.cur_pic; |
| if (pic) { |
| dec->avs3_dec.cur_pic->decoded_lcu = |
| (READ_VREG(HEVC_PARSER_LCU_START) |
| & 0xffffff) + 1; |
| avs3_print(dec, AVS3_DBG_BUFMGR_MORE, |
| "%s pic(index %d) decoded lcu %d (total %d)\n", |
| __func__, pic->index, |
| pic->decoded_lcu, dec->avs3_dec.lcu_total); |
| } |
| } |
| /* +[SE] [BUG][BUG-171463][chuanqi.wang]: get frame rate by video sequeue*/ |
| static int get_frame_rate(union param_u *params, struct AVS3Decoder_s *dec) |
| { |
| int tmp = 0; |
| |
| switch (params->p.sqh_frame_rate_code) { |
| case 1: |
| case 2: |
| tmp = 24; |
| break; |
| case 3: |
| tmp = 25; |
| break; |
| case 4: |
| case 5: |
| tmp = 30; |
| break; |
| case 6: |
| tmp = 50; |
| break; |
| case 7: |
| case 8: |
| tmp = 60; |
| break; |
| case 9: |
| tmp = 100; |
| break; |
| case 10: |
| tmp = 120; |
| break; |
| default: |
| tmp = 25; |
| break; |
| } |
| |
| if (!params->p.sqh_progressive_sequence) |
| tmp = tmp / 2; |
| dec->frame_dur = div_u64(96000ULL, tmp); |
| dec->get_frame_dur = true; |
| /*avs3_print(dec, 0, "avs3 frame_dur:%d,progressive:%d\n", dec->frame_dur, params->p.progressive_sequence);*/ |
| return 0; |
| } |
| |
| #define HEVC_MV_INFO 0x310d |
| #define HEVC_QP_INFO 0x3137 |
| #define HEVC_SKIP_INFO 0x3136 |
| |
| /* only when we decoded one field or one frame, |
| we can call this function to get qos info*/ |
| static void get_picture_qos_info(struct AVS3Decoder_s *dec) |
| { |
| struct avs3_frame_s *picture = dec->avs3_dec.cur_pic; |
| struct vdec_s *vdec = hw_to_vdec(dec); |
| if (!picture) { |
| avs3_print(dec, AVS3_DBG_BUFMGR_MORE, |
| "%s decode picture is none exist\n"); |
| |
| return; |
| } |
| if (vdec->mvfrm) { |
| picture->frame_size = vdec->mvfrm->frame_size; |
| picture->hw_decode_time = |
| local_clock() - vdec->mvfrm->hw_decode_start; |
| } |
| |
| /* |
| #define DEBUG_QOS |
| */ |
| |
| if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_G12A) { |
| unsigned char a[3]; |
| unsigned char i, j, t; |
| unsigned long data; |
| |
| data = READ_VREG(HEVC_MV_INFO); |
| if (picture->slice_type == I_IMG) |
| data = 0; |
| a[0] = data & 0xff; |
| a[1] = (data >> 8) & 0xff; |
| a[2] = (data >> 16) & 0xff; |
| |
| for (i = 0; i < 3; i++) |
| for (j = i+1; j < 3; j++) { |
| if (a[j] < a[i]) { |
| t = a[j]; |
| a[j] = a[i]; |
| a[i] = t; |
| } else if (a[j] == a[i]) { |
| a[i]++; |
| t = a[j]; |
| a[j] = a[i]; |
| a[i] = t; |
| } |
| } |
| picture->max_mv = a[2]; |
| picture->avg_mv = a[1]; |
| picture->min_mv = a[0]; |
| #ifdef DEBUG_QOS |
| avs3_print(dec, 0, "mv data %x a[0]= %x a[1]= %x a[2]= %x\n", |
| data, a[0], a[1], a[2]); |
| #endif |
| |
| data = READ_VREG(HEVC_QP_INFO); |
| a[0] = data & 0x1f; |
| a[1] = (data >> 8) & 0x3f; |
| a[2] = (data >> 16) & 0x7f; |
| |
| for (i = 0; i < 3; i++) |
| for (j = i+1; j < 3; j++) { |
| if (a[j] < a[i]) { |
| t = a[j]; |
| a[j] = a[i]; |
| a[i] = t; |
| } else if (a[j] == a[i]) { |
| a[i]++; |
| t = a[j]; |
| a[j] = a[i]; |
| a[i] = t; |
| } |
| } |
| picture->max_qp = a[2]; |
| picture->avg_qp = a[1]; |
| picture->min_qp = a[0]; |
| #ifdef DEBUG_QOS |
| avs3_print(dec, 0, "qp data %x a[0]= %x a[1]= %x a[2]= %x\n", |
| data, a[0], a[1], a[2]); |
| #endif |
| |
| data = READ_VREG(HEVC_SKIP_INFO); |
| a[0] = data & 0x1f; |
| a[1] = (data >> 8) & 0x3f; |
| a[2] = (data >> 16) & 0x7f; |
| |
| for (i = 0; i < 3; i++) |
| for (j = i+1; j < 3; j++) { |
| if (a[j] < a[i]) { |
| t = a[j]; |
| a[j] = a[i]; |
| a[i] = t; |
| } else if (a[j] == a[i]) { |
| a[i]++; |
| t = a[j]; |
| a[j] = a[i]; |
| a[i] = t; |
| } |
| } |
| picture->max_skip = a[2]; |
| picture->avg_skip = a[1]; |
| picture->min_skip = a[0]; |
| |
| #ifdef DEBUG_QOS |
| avs3_print(dec, 0, |
| "skip data %x a[0]= %x a[1]= %x a[2]= %x\n", |
| data, a[0], a[1], a[2]); |
| #endif |
| } else { |
| uint32_t blk88_y_count; |
| uint32_t blk88_c_count; |
| uint32_t blk22_mv_count; |
| uint32_t rdata32; |
| int32_t mv_hi; |
| int32_t mv_lo; |
| uint32_t rdata32_l; |
| uint32_t mvx_L0_hi; |
| uint32_t mvy_L0_hi; |
| uint32_t mvx_L1_hi; |
| uint32_t mvy_L1_hi; |
| int64_t value; |
| uint64_t temp_value; |
| #ifdef DEBUG_QOS |
| int pic_number = 0; |
| #endif |
| |
| picture->max_mv = 0; |
| picture->avg_mv = 0; |
| picture->min_mv = 0; |
| |
| picture->max_skip = 0; |
| picture->avg_skip = 0; |
| picture->min_skip = 0; |
| |
| picture->max_qp = 0; |
| picture->avg_qp = 0; |
| picture->min_qp = 0; |
| |
| #ifdef DEBUG_QOS |
| avs3_print(dec, 0, "slice_type:%d, poc:%d\n", |
| picture->slice_type, |
| pic_number); |
| #endif |
| /* set rd_idx to 0 */ |
| WRITE_VREG(HEVC_PIC_QUALITY_CTRL, 0); |
| |
| blk88_y_count = READ_VREG(HEVC_PIC_QUALITY_DATA); |
| if (blk88_y_count == 0) { |
| #ifdef DEBUG_QOS |
| avs3_print(dec, 0, |
| "[Picture %d Quality] NO Data yet.\n", |
| pic_number); |
| #endif |
| /* reset all counts */ |
| WRITE_VREG(HEVC_PIC_QUALITY_CTRL, (1<<8)); |
| return; |
| } |
| /* qp_y_sum */ |
| rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); |
| #ifdef DEBUG_QOS |
| avs3_print(dec, 0, |
| "[Picture %d Quality] Y QP AVG : %d (%d/%d)\n", |
| pic_number, rdata32/blk88_y_count, |
| rdata32, blk88_y_count); |
| #endif |
| picture->avg_qp = rdata32/blk88_y_count; |
| /* intra_y_count */ |
| rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); |
| #ifdef DEBUG_QOS |
| avs3_print(dec, 0, |
| "[Picture %d Quality] Y intra rate : %d%c (%d)\n", |
| pic_number, rdata32*100/blk88_y_count, |
| '%', rdata32); |
| #endif |
| /* skipped_y_count */ |
| rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); |
| #ifdef DEBUG_QOS |
| avs3_print(dec, 0, |
| "[Picture %d Quality] Y skipped rate : %d%c (%d)\n", |
| pic_number, rdata32*100/blk88_y_count, |
| '%', rdata32); |
| #endif |
| picture->avg_skip = rdata32*100/blk88_y_count; |
| /* coeff_non_zero_y_count */ |
| rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); |
| #ifdef DEBUG_QOS |
| avs3_print(dec, 0, |
| "[Picture %d Quality] Y ZERO_Coeff rate : %d%c (%d)\n", |
| pic_number, (100 - rdata32*100/(blk88_y_count*1)), |
| '%', rdata32); |
| #endif |
| /* blk66_c_count */ |
| blk88_c_count = READ_VREG(HEVC_PIC_QUALITY_DATA); |
| if (blk88_c_count == 0) { |
| #ifdef DEBUG_QOS |
| avs3_print(dec, 0, |
| "[Picture %d Quality] NO Data yet.\n", |
| pic_number); |
| #endif |
| /* reset all counts */ |
| WRITE_VREG(HEVC_PIC_QUALITY_CTRL, (1<<8)); |
| return; |
| } |
| /* qp_c_sum */ |
| rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); |
| #ifdef DEBUG_QOS |
| avs3_print(dec, 0, |
| "[Picture %d Quality] C QP AVG : %d (%d/%d)\n", |
| pic_number, rdata32/blk88_c_count, |
| rdata32, blk88_c_count); |
| #endif |
| /* intra_c_count */ |
| rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); |
| #ifdef DEBUG_QOS |
| avs3_print(dec, 0, |
| "[Picture %d Quality] C intra rate : %d%c (%d)\n", |
| pic_number, rdata32*100/blk88_c_count, |
| '%', rdata32); |
| #endif |
| /* skipped_cu_c_count */ |
| rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); |
| #ifdef DEBUG_QOS |
| avs3_print(dec, 0, |
| "[Picture %d Quality] C skipped rate : %d%c (%d)\n", |
| pic_number, rdata32*100/blk88_c_count, |
| '%', rdata32); |
| #endif |
| /* coeff_non_zero_c_count */ |
| rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); |
| #ifdef DEBUG_QOS |
| avs3_print(dec, 0, |
| "[Picture %d Quality] C ZERO_Coeff rate : %d%c (%d)\n", |
| pic_number, (100 - rdata32*100/(blk88_c_count*1)), |
| '%', rdata32); |
| #endif |
| |
| /* 1'h0, qp_c_max[6:0], 1'h0, qp_c_min[6:0], |
| 1'h0, qp_y_max[6:0], 1'h0, qp_y_min[6:0] */ |
| rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); |
| #ifdef DEBUG_QOS |
| avs3_print(dec, 0, "[Picture %d Quality] Y QP min : %d\n", |
| pic_number, (rdata32>>0)&0xff); |
| #endif |
| picture->min_qp = (rdata32>>0)&0xff; |
| |
| #ifdef DEBUG_QOS |
| avs3_print(dec, 0, "[Picture %d Quality] Y QP max : %d\n", |
| pic_number, (rdata32>>8)&0xff); |
| #endif |
| picture->max_qp = (rdata32>>8)&0xff; |
| |
| #ifdef DEBUG_QOS |
| avs3_print(dec, 0, "[Picture %d Quality] C QP min : %d\n", |
| pic_number, (rdata32>>16)&0xff); |
| avs3_print(dec, 0, "[Picture %d Quality] C QP max : %d\n", |
| pic_number, (rdata32>>24)&0xff); |
| #endif |
| |
| /* blk22_mv_count */ |
| blk22_mv_count = READ_VREG(HEVC_PIC_QUALITY_DATA); |
| if (blk22_mv_count == 0) { |
| #ifdef DEBUG_QOS |
| avs3_print(dec, 0, |
| "[Picture %d Quality] NO MV Data yet.\n", |
| pic_number); |
| #endif |
| /* reset all counts */ |
| WRITE_VREG(HEVC_PIC_QUALITY_CTRL, (1<<8)); |
| return; |
| } |
| /* mvy_L1_count[39:32], mvx_L1_count[39:32], |
| mvy_L0_count[39:32], mvx_L0_count[39:32] */ |
| rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); |
| /* should all be 0x00 or 0xff */ |
| #ifdef DEBUG_QOS |
| avs3_print(dec, 0, |
| "[Picture %d Quality] MV AVG High Bits: 0x%X\n", |
| pic_number, rdata32); |
| #endif |
| mvx_L0_hi = ((rdata32>>0)&0xff); |
| mvy_L0_hi = ((rdata32>>8)&0xff); |
| mvx_L1_hi = ((rdata32>>16)&0xff); |
| mvy_L1_hi = ((rdata32>>24)&0xff); |
| |
| /* mvx_L0_count[31:0] */ |
| rdata32_l = READ_VREG(HEVC_PIC_QUALITY_DATA); |
| temp_value = mvx_L0_hi; |
| temp_value = (temp_value << 32) | rdata32_l; |
| |
| if (mvx_L0_hi & 0x80) |
| value = 0xFFFFFFF000000000 | temp_value; |
| else |
| value = temp_value; |
| value = div_s64(value, blk22_mv_count); |
| #ifdef DEBUG_QOS |
| avs3_print(dec, 0, |
| "[Picture %d Quality] MVX_L0 AVG : %d (%lld/%d)\n", |
| pic_number, (int)value, |
| value, blk22_mv_count); |
| #endif |
| picture->avg_mv = value; |
| |
| /* mvy_L0_count[31:0] */ |
| rdata32_l = READ_VREG(HEVC_PIC_QUALITY_DATA); |
| temp_value = mvy_L0_hi; |
| temp_value = (temp_value << 32) | rdata32_l; |
| |
| if (mvy_L0_hi & 0x80) |
| value = 0xFFFFFFF000000000 | temp_value; |
| else |
| value = temp_value; |
| #ifdef DEBUG_QOS |
| avs3_print(dec, 0, |
| "[Picture %d Quality] MVY_L0 AVG : %d (%lld/%d)\n", |
| pic_number, rdata32_l/blk22_mv_count, |
| value, blk22_mv_count); |
| #endif |
| |
| /* mvx_L1_count[31:0] */ |
| rdata32_l = READ_VREG(HEVC_PIC_QUALITY_DATA); |
| temp_value = mvx_L1_hi; |
| temp_value = (temp_value << 32) | rdata32_l; |
| if (mvx_L1_hi & 0x80) |
| value = 0xFFFFFFF000000000 | temp_value; |
| else |
| value = temp_value; |
| #ifdef DEBUG_QOS |
| avs3_print(dec, 0, |
| "[Picture %d Quality] MVX_L1 AVG : %d (%lld/%d)\n", |
| pic_number, rdata32_l/blk22_mv_count, |
| value, blk22_mv_count); |
| #endif |
| |
| /* mvy_L1_count[31:0] */ |
| rdata32_l = READ_VREG(HEVC_PIC_QUALITY_DATA); |
| temp_value = mvy_L1_hi; |
| temp_value = (temp_value << 32) | rdata32_l; |
| if (mvy_L1_hi & 0x80) |
| value = 0xFFFFFFF000000000 | temp_value; |
| else |
| value = temp_value; |
| #ifdef DEBUG_QOS |
| avs3_print(dec, 0, |
| "[Picture %d Quality] MVY_L1 AVG : %d (%lld/%d)\n", |
| pic_number, rdata32_l/blk22_mv_count, |
| value, blk22_mv_count); |
| #endif |
| |
| /* {mvx_L0_max, mvx_L0_min} // format : {sign, abs[14:0]} */ |
| rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); |
| mv_hi = (rdata32>>16)&0xffff; |
| if (mv_hi & 0x8000) |
| mv_hi = 0x8000 - mv_hi; |
| #ifdef DEBUG_QOS |
| avs3_print(dec, 0, "[Picture %d Quality] MVX_L0 MAX : %d\n", |
| pic_number, mv_hi); |
| #endif |
| picture->max_mv = mv_hi; |
| |
| mv_lo = (rdata32>>0)&0xffff; |
| if (mv_lo & 0x8000) |
| mv_lo = 0x8000 - mv_lo; |
| #ifdef DEBUG_QOS |
| avs3_print(dec, 0, "[Picture %d Quality] MVX_L0 MIN : %d\n", |
| pic_number, mv_lo); |
| #endif |
| picture->min_mv = mv_lo; |
| |
| #ifdef DEBUG_QOS |
| /* {mvy_L0_max, mvy_L0_min} */ |
| rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); |
| mv_hi = (rdata32>>16)&0xffff; |
| if (mv_hi & 0x8000) |
| mv_hi = 0x8000 - mv_hi; |
| avs3_print(dec, 0, "[Picture %d Quality] MVY_L0 MAX : %d\n", |
| pic_number, mv_hi); |
| |
| mv_lo = (rdata32>>0)&0xffff; |
| if (mv_lo & 0x8000) |
| mv_lo = 0x8000 - mv_lo; |
| |
| avs3_print(dec, 0, "[Picture %d Quality] MVY_L0 MIN : %d\n", |
| pic_number, mv_lo); |
| |
| /* {mvx_L1_max, mvx_L1_min} */ |
| rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); |
| mv_hi = (rdata32>>16)&0xffff; |
| if (mv_hi & 0x8000) |
| mv_hi = 0x8000 - mv_hi; |
| |
| avs3_print(dec, 0, "[Picture %d Quality] MVX_L1 MAX : %d\n", |
| pic_number, mv_hi); |
| |
| mv_lo = (rdata32>>0)&0xffff; |
| if (mv_lo & 0x8000) |
| mv_lo = 0x8000 - mv_lo; |
| |
| avs3_print(dec, 0, "[Picture %d Quality] MVX_L1 MIN : %d\n", |
| pic_number, mv_lo); |
| |
| /* {mvy_L1_max, mvy_L1_min} */ |
| rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); |
| mv_hi = (rdata32>>16)&0xffff; |
| if (mv_hi & 0x8000) |
| mv_hi = 0x8000 - mv_hi; |
| |
| avs3_print(dec, 0, "[Picture %d Quality] MVY_L1 MAX : %d\n", |
| pic_number, mv_hi); |
| |
| mv_lo = (rdata32>>0)&0xffff; |
| if (mv_lo & 0x8000) |
| mv_lo = 0x8000 - mv_lo; |
| |
| avs3_print(dec, 0, "[Picture %d Quality] MVY_L1 MIN : %d\n", |
| pic_number, mv_lo); |
| #endif |
| |
| rdata32 = READ_VREG(HEVC_PIC_QUALITY_CTRL); |
| #ifdef DEBUG_QOS |
| avs3_print(dec, 0, |
| "[Picture %d Quality] After Read : VDEC_PIC_QUALITY_CTRL : 0x%x\n", |
| pic_number, rdata32); |
| #endif |
| /* reset all counts */ |
| WRITE_VREG(HEVC_PIC_QUALITY_CTRL, (1<<8)); |
| } |
| } |
| |
| #ifdef NEW_FB_CODE |
| irqreturn_t avs3_back_irq_cb(struct vdec_s *vdec, int irq) |
| { |
| struct AVS3Decoder_s *dec = |
| (struct AVS3Decoder_s *)vdec->private; |
| |
| ATRACE_COUNTER(dec->trace.decode_back_time_name, DECODER_ISR_PIC_DONE); |
| dec->dec_status_back = READ_VREG(HEVC_DEC_STATUS_DBE); |
| if (dec->dec_status_back == HEVC_BE_DECODE_DATA_DONE) { |
| vdec_profile(hw_to_vdec(dec), VDEC_PROFILE_DECODER_END, CORE_MASK_HEVC_BACK); |
| } |
| |
| /*BackEnd_Handle()*/ |
| if (dec->front_back_mode != 1) { |
| avs3_print(dec, AVS3_DBG_IRQ_EVENT, |
| "[BE] %s\n", __func__); |
| if (dec->front_back_mode == 3) |
| dec->dec_status_back = HEVC_BE_DECODE_DATA_DONE; |
| return IRQ_WAKE_THREAD; |
| } |
| |
| #if 0 |
| if (debug & AVS3_DBG_IRQ_EVENT) |
| avs3_print(dec, 0, |
| "[BE] avs3 back isr dec_status_back = 0x%x\n", |
| dec->dec_status_back |
| ); |
| if (READ_VREG(DEBUG_REG1_DBE)) { |
| pr_info("[BE] dbg%x: %x, HEVC_SAO_CRC %x HEVC_SAO_CRC_DBE1 %x\n", READ_VREG(DEBUG_REG1_DBE), |
| READ_VREG(DEBUG_REG2_DBE), |
| READ_VREG(HEVC_SAO_CRC), |
| READ_VREG(HEVC_SAO_CRC_DBE1) |
| ); |
| WRITE_VREG(DEBUG_REG1_DBE, 0); |
| } |
| #else |
| if (READ_VREG(DEBUG_REG1_DBE)) { |
| #ifdef USE_FRONT_ISR_HANDLE_FOR_BACK |
| WRITE_VREG(dec->ASSIST_MBOX0_IRQ_REG, 0x1); |
| ATRACE_COUNTER(dec->trace.decode_back_time_name, DECODER_ISR_END); |
| return IRQ_HANDLED; |
| #else |
| ATRACE_COUNTER(dec->trace.decode_back_time_name, DECODER_ISR_END); |
| return IRQ_WAKE_THREAD; |
| #endif |
| } |
| #endif |
| if (dec->dec_status_back == AVS3_DEC_IDLE) { |
| ATRACE_COUNTER(dec->trace.decode_back_time_name, DECODER_ISR_END); |
| return IRQ_HANDLED; |
| } |
| /**/ |
| #ifdef USE_FRONT_ISR_HANDLE_FOR_BACK |
| WRITE_VREG(dec->ASSIST_MBOX0_IRQ_REG, 0x1); |
| ATRACE_COUNTER(dec->trace.decode_back_time_name, DECODER_ISR_END); |
| return IRQ_HANDLED; |
| #else |
| ATRACE_COUNTER(dec->trace.decode_back_time_name, DECODER_ISR_END); |
| return IRQ_WAKE_THREAD; |
| #endif |
| } |
| |
| irqreturn_t vavs3_back_isr_thread_fn(struct AVS3Decoder_s *dec) |
| { |
| unsigned int dec_status = dec->dec_status_back; |
| struct avs3_decoder *avs3_dec = &dec->avs3_dec; |
| struct vdec_s *vdec = hw_to_vdec(dec); |
| int j; |
| //unsigned long flags; |
| //lock_front_back(dec, flags); |
| ATRACE_COUNTER(dec->trace.decode_back_time_name, DECODER_ISR_THREAD_PIC_DONE_START); |
| |
| #if 1 |
| if (debug & AVS3_DBG_IRQ_EVENT) |
| avs3_print(dec, 0, |
| "[BE] avs3 back isr dec_status_back = 0x%x\n", |
| dec->dec_status_back |
| ); |
| if (READ_VREG(DEBUG_REG1_DBE)) { |
| pr_info("[BE] dbg%x: %x\n", READ_VREG(DEBUG_REG1_DBE), |
| READ_VREG(DEBUG_REG2_DBE) |
| ); |
| WRITE_VREG(DEBUG_REG1_DBE, 0); |
| } |
| #endif |
| /*simulation code: if (READ_VREG(HEVC_DEC_STATUS_DBE)==HEVC_BE_DECODE_DATA_DONE)*/ |
| if (dec_status == HEVC_BE_DECODE_DATA_DONE || dec->front_back_mode == 2) { |
| struct avs3_frame_s *pic = avs3_dec->next_be_decode_pic[avs3_dec->fb_rd_pos]; |
| struct avs3_frame_s *ref_pic = NULL; |
| |
| reset_process_time_back(dec); |
| vdec->back_pic_done = true; |
| avs3_print(dec, PRINT_FLAG_VDEC_STATUS, |
| "BackEnd data done %d, fb_rd_pos %d, pic index %d, HEVC_SAO_CRC %x HEVC_SAO_CRC_DBE1 %x\n", |
| avs3_dec->backend_decoded_count, avs3_dec->fb_rd_pos, pic->index, |
| READ_VREG(HEVC_SAO_CRC), READ_VREG(HEVC_SAO_CRC_DBE1)); |
| |
| if (debug & AVS3_DBG_BUFMGR_DETAIL) { |
| pr_info("[BE] HEVC_CM_BODY_START_ADDR = %x\n", READ_VREG(HEVC_CM_BODY_START_ADDR)); |
| pr_info("[BE] HEVC_CM_HEADER_START_ADDR = %x\n", READ_VREG(HEVC_CM_HEADER_START_ADDR)); |
| pr_info("[BE] HEVC_SAO_Y_START_ADDR = %x\n", READ_VREG(HEVC_SAO_Y_START_ADDR)); |
| pr_info("[BE] HEVC_SAO_Y_LENGTH = %x\n", READ_VREG(HEVC_SAO_Y_LENGTH)); |
| pr_info("[BE] HEVC_SAO_C_START_ADDR = %x\n", READ_VREG(HEVC_SAO_C_START_ADDR)); |
| pr_info("[BE] HEVC_SAO_C_LENGTH = %x\n", READ_VREG(HEVC_SAO_C_LENGTH)); |
| pr_info("[BE] HEVC_SAO_Y_WPTR = %x\n", READ_VREG(HEVC_SAO_Y_WPTR)); |
| pr_info("[BE] HEVC_SAO_C_WPTR = %x\n", READ_VREG(HEVC_SAO_C_WPTR)); |
| pr_info("[BE] HEVC_SAO_CTRL0 = %x\n", READ_VREG(HEVC_SAO_CTRL0)); |
| pr_info("[BE] HEVC_SAO_CTRL1 = %x\n", READ_VREG(HEVC_SAO_CTRL1)); |
| pr_info("[BE] HEVC_SAO_CTRL2 = %x\n", READ_VREG(HEVC_SAO_CTRL2)); |
| pr_info("[BE] HEVC_SAO_CTRL3 = %x\n", READ_VREG(HEVC_SAO_CTRL3)); |
| pr_info("[BE] HEVC_SAO_CTRL4 = %x\n", READ_VREG(HEVC_SAO_CTRL4)); |
| pr_info("[BE] HEVC_SAO_CTRL5 = %x\n", READ_VREG(HEVC_SAO_CTRL5)); |
| |
| pr_info("[BE] HEVC_CM_BODY_START_ADDR_DBE1 = %x\n", READ_VREG(HEVC_CM_BODY_START_ADDR_DBE1)); |
| pr_info("[BE] HEVC_CM_HEADER_START_ADDR_DBE1 = %x\n", READ_VREG(HEVC_CM_HEADER_START_ADDR_DBE1)); |
| pr_info("[BE] HEVC_SAO_Y_START_ADDR_DBE1 = %x\n", READ_VREG(HEVC_SAO_Y_START_ADDR_DBE1)); |
| pr_info("[BE] HEVC_SAO_Y_LENGTH_DBE1 = %x\n", READ_VREG(HEVC_SAO_Y_LENGTH_DBE1)); |
| pr_info("[BE] HEVC_SAO_C_START_ADDR_DBE1 = %x\n", READ_VREG(HEVC_SAO_C_START_ADDR_DBE1)); |
| pr_info("[BE] HEVC_SAO_C_LENGTH_DBE1 = %x\n", READ_VREG(HEVC_SAO_C_LENGTH_DBE1)); |
| pr_info("[BE] HEVC_SAO_Y_WPTR_DBE1 = %x\n", READ_VREG(HEVC_SAO_Y_WPTR_DBE1)); |
| pr_info("[BE] HEVC_SAO_C_WPTR_DBE1 = %x\n", READ_VREG(HEVC_SAO_C_WPTR_DBE1)); |
| pr_info("[BE] HEVC_SAO_CTRL0_DBE1 = %x\n", READ_VREG(HEVC_SAO_CTRL0_DBE1)); |
| pr_info("[BE] HEVC_SAO_CTRL1_DBE1 = %x\n", READ_VREG(HEVC_SAO_CTRL1_DBE1)); |
| pr_info("[BE] HEVC_SAO_CTRL2_DBE1 = %x\n", READ_VREG(HEVC_SAO_CTRL2_DBE1)); |
| pr_info("[BE] HEVC_SAO_CTRL3_DBE1 = %x\n", READ_VREG(HEVC_SAO_CTRL3_DBE1)); |
| pr_info("[BE] HEVC_SAO_CTRL4_DBE1 = %x\n", READ_VREG(HEVC_SAO_CTRL4_DBE1)); |
| pr_info("[BE] HEVC_SAO_CTRL5_DBE1 = %x\n", READ_VREG(HEVC_SAO_CTRL5_DBE1)); |
| } |
| |
| if (fbdebug_flag & 0x70000000) { |
| u8 cmd = (fbdebug_flag >> 28) & 0x7; |
| u32 dump_c = (fbdebug_flag >> 16) & 0xfff; |
| if ((cmd == 3) || |
| (cmd == 1 && dump_c == avs3_dec->backend_decoded_count) || |
| (cmd == 2 && avs3_dec->backend_decoded_count < dump_c)) |
| //10000, make log different from dump_loop_buffer after FrontEnd data done. |
| dump_loop_buffer(dec, 10000 + avs3_dec->backend_decoded_count, cmd ==1 || cmd == 2); |
| } |
| |
| if (dec->front_back_mode == 1) { |
| avs3_print(dec, PRINT_FLAG_VDEC_DETAIL, |
| "MMU0 b cur addr : 0x%x\n", READ_VREG(HEVC_ASSIST_FBD_MMU_MAP_ADDR0)); |
| avs3_print(dec, PRINT_FLAG_VDEC_DETAIL, |
| "MMU1 b cur addr : 0x%x\n", READ_VREG(HEVC_ASSIST_FBD_MMU_MAP_ADDR1)); |
| WRITE_VREG(HEVC_DEC_STATUS_DBE, AVS3_DEC_IDLE); |
| WRITE_VREG(HEVC_ASSIST_FB_PIC_CLR, 2); |
| } |
| if (debug & AVS3_DBG_PRINT_PIC_LIST) { |
| print_pic_pool(avs3_dec, "before dec backend_ref"); |
| avs3_print_cont(dec, 0, "pic_cfg index %d, list0 index ", pic->index); |
| for (j = 0; j < pic->list0_num_refp; j++) |
| avs3_print_cont(dec, 0, "%d ", pic->list0_index[j]); |
| avs3_print_cont(dec, 0, "list1 index "); |
| for (j = 0; j < pic->list1_num_refp; j++) |
| avs3_print_cont(dec, 0, "%d ", pic->list1_index[j]); |
| avs3_print(dec, 0, "\n"); |
| } |
| avs3_dec->backend_decoded_count++; |
| pic->backend_ref--; |
| for (j = 0; j < pic->list0_num_refp; j++) { |
| ref_pic = &avs3_dec->pic_pool[pic->list0_index[j]].buf_cfg; |
| ref_pic->backend_ref--; |
| if (ref_pic->backend_ref < 0) { |
| ref_pic->backend_ref = 0; |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, "%s:L0 ref_pic %d backend_ref error\n", __func__, j); |
| } |
| if (ref_pic->error_mark) { |
| pic->error_mark = 1; |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, "%s:L0 refid %d pic error\n", __func__, j); |
| } |
| } |
| for (j = 0; j < pic->list1_num_refp; j++) { |
| ref_pic = &avs3_dec->pic_pool[pic->list1_index[j]].buf_cfg; |
| ref_pic->backend_ref--; |
| if (ref_pic->backend_ref < 0) { |
| ref_pic->backend_ref = 0; |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, "%s:L1 ref_pic %d backend_ref error\n", __func__, j); |
| } |
| if (ref_pic->error_mark) { |
| pic->error_mark = 1; |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, "%s:L1 refid %d pic error\n", __func__, j); |
| } |
| } |
| pic->back_done_mark = 1; |
| //if (debug&H265_DEBUG_BUFMGR_MORE) dump_pic_list(dec); |
| if (debug & AVS3_DBG_PRINT_PIC_LIST) |
| print_pic_pool(avs3_dec, "after dec backend_ref"); |
| |
| #if 0 |
| #ifdef AVS3_10B_MMU |
| release_unused_4k(&avs3_mmumgr_0, pic->index); |
| release_unused_4k(&avs3_mmumgr_1, pic->index); |
| #endif |
| #ifdef AVS3_10B_MMU_DW |
| release_unused_4k(&avs3_mmumgr_dw0, pic->index); // new dual |
| release_unused_4k(&avs3_mmumgr_dw1, pic->index); // new dual |
| #endif |
| #else |
| if ((dec->front_back_mode == 1 || |
| dec->front_back_mode == 3 |
| ) && (debug & AVS3_DBG_NOT_RECYCLE_MMU_TAIL) == 0) { |
| /*if (dec->is_used_v4l) { |
| // to do |
| } else {*/ |
| unsigned used_4k_num0; |
| unsigned used_4k_num1; |
| used_4k_num0 = READ_VREG(HEVC_SAO_MMU_STATUS) >> 16; |
| if (dec->front_back_mode == 3) |
| used_4k_num1 = used_4k_num0; |
| else |
| used_4k_num1 = READ_VREG(HEVC_SAO_MMU_STATUS_DBE1) >> 16; |
| avs3_print(dec, AVS3_DBG_BUFMGR_MORE, |
| "%s decoder_mmu_box_free_idx_tail index=%d, core0 %d core1 %d\n", |
| __func__, pic->index, |
| used_4k_num0, used_4k_num1); |
| decoder_mmu_box_free_idx_tail( |
| dec->mmu_box, |
| pic->index, |
| used_4k_num0); |
| decoder_mmu_box_free_idx_tail( |
| dec->mmu_box_1, |
| pic->index, |
| used_4k_num1); |
| if (dec->dw_mmu_enable) { |
| used_4k_num0 = READ_VREG(HEVC_SAO_MMU_STATUS2) >> 16; |
| if (dec->front_back_mode == 3) |
| used_4k_num1 = used_4k_num0; |
| else |
| used_4k_num1 = READ_VREG(HEVC_SAO_MMU_STATUS2_DBE1) >> 16; |
| avs3_print(dec, AVS3_DBG_BUFMGR_MORE, |
| "%s DW decoder_mmu_box_free_idx_tail index=%d, core0 %d core1 %d\n", |
| __func__, pic->index, |
| used_4k_num0, used_4k_num1); |
| decoder_mmu_box_free_idx_tail( |
| dec->dw_mmu_box, |
| pic->index, |
| used_4k_num0); |
| decoder_mmu_box_free_idx_tail( |
| dec->dw_mmu_box_1, |
| pic->index, |
| used_4k_num1); |
| } |
| /*} |
| pic->scatter_alloc = 2;*/ |
| } |
| #endif |
| //pr_err("sleep in\n"); |
| //usleep_range(1000, 2000); |
| //pr_err("sleep out\n"); |
| mutex_lock(&dec->fb_mutex); |
| avs3_dec->fb_rd_pos++; |
| if (avs3_dec->fb_rd_pos >= dec->fb_ifbuf_num) |
| avs3_dec->fb_rd_pos = 0; |
| |
| avs3_dec->wait_working_buf = 0; |
| avs3_print(dec, PRINT_FLAG_VDEC_DETAIL, |
| "fb_wr_pos %d, set next fb_rd_pos %d, set wait_working_buf %d\n", |
| avs3_dec->fb_wr_pos, avs3_dec->fb_rd_pos, avs3_dec->wait_working_buf); |
| |
| mutex_unlock(&dec->fb_mutex); |
| |
| if (without_display_mode == 0) { |
| struct vframe_s *vf = NULL; |
| if (kfifo_peek(&dec->display_q, &vf) && vf) { |
| uint8_t index = vf->index & 0xff; |
| struct avs3_frame_s *peek_pic = get_pic_by_index(dec, index); |
| if (peek_pic == pic) |
| vf_notify_receiver(dec->provider_name, |
| VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); |
| } |
| } else |
| vavs3_vf_put(vavs3_vf_get(dec), dec); |
| |
| #if 1 //def RESET_BACK_PER_PICTURE |
| if (dec->front_back_mode == 1) |
| amhevc_stop_b(); |
| #endif |
| if (dec->front_back_mode == 1 || |
| dec->front_back_mode == 3) |
| release_free_mmu_buffers(dec); |
| |
| dec->dec_back_result = DEC_BACK_RESULT_DONE; |
| ATRACE_COUNTER(dec->trace.decode_back_time_name, DECODER_ISR_THREAD_EDN); |
| vdec_schedule_work(&dec->work_back); |
| if (avs3_dec->front_pause_flag) { |
| /*multi pictures in one packe*/ |
| WRITE_VREG(dec->ASSIST_MBOX0_IRQ_REG, |
| 0x1); |
| } |
| } |
| //unlock_front_back(dec, flags); |
| |
| return IRQ_HANDLED; |
| } |
| |
| irqreturn_t avs3_back_threaded_irq_cb(struct vdec_s *vdec, int irq) |
| { |
| struct AVS3Decoder_s *dec = |
| (struct AVS3Decoder_s *)vdec->private; |
| irqreturn_t ret; |
| //unsigned long flags; |
| //lock_front_back(dec, flags); |
| ret = vavs3_back_isr_thread_fn(dec); |
| //unlock_front_back(dec, flags); |
| return ret; |
| } |
| |
| #endif |
| |
| static void handle_ucode_dbg(struct AVS3Decoder_s *dec, uint debug_tag) |
| { |
| |
| int i; |
| if (debug_tag & 0x10000) { |
| dma_sync_single_for_cpu( |
| amports_get_dma_device(), |
| dec->lmem_phy_addr, |
| LMEM_BUF_SIZE, |
| DMA_FROM_DEVICE); |
| |
| pr_info("LMEM<tag %x>:\n", READ_HREG(DEBUG_REG1)); |
| for (i = 0; i < 0x400; i += 4) { |
| int ii; |
| if ((i & 0xf) == 0) |
| pr_info("%03x: ", i); |
| for (ii = 0; ii < 4; ii++) { |
| pr_info("%04x ", |
| dec->lmem_ptr[i + 3 - ii]); |
| } |
| if (((i + ii) & 0xf) == 0) |
| pr_info("\n"); |
| } |
| |
| if (((udebug_pause_pos & 0xffff) |
| == (debug_tag & 0xffff)) && |
| (udebug_pause_decode_idx == 0 || |
| udebug_pause_decode_idx == dec->decode_idx) && |
| (udebug_pause_val == 0 || |
| udebug_pause_val == READ_HREG(DEBUG_REG2))) { |
| udebug_pause_pos &= 0xffff; |
| dec->ucode_pause_pos = udebug_pause_pos; |
| } else if (debug_tag & 0x20000) |
| dec->ucode_pause_pos = 0xffffffff; |
| if (dec->ucode_pause_pos) |
| reset_process_time(dec); |
| else |
| WRITE_VREG(DEBUG_REG1, 0); |
| } else if (debug_tag != 0) { |
| pr_info( |
| "dbg%x: %x lcu %x stream crc %x, shiftbytes 0x%x decbytes 0x%x\n", READ_HREG(DEBUG_REG1), |
| READ_HREG(DEBUG_REG2), |
| READ_VREG(HEVC_PARSER_LCU_START), |
| READ_VREG(HEVC_STREAM_CRC), READ_VREG(HEVC_SHIFT_BYTE_COUNT), |
| READ_VREG(HEVC_SHIFT_BYTE_COUNT) - |
| dec->start_shift_bytes); |
| if ((debug & AVS3_DBG_SAO_CRC) && |
| (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_S5)) { |
| unsigned old_crc = READ_VREG(HEVC_SAO_CRC); |
| int count = 0; |
| while (1) { |
| unsigned crc; |
| crc = READ_VREG(HEVC_SAO_CRC); |
| if (crc == old_crc) { |
| pr_info("stable HEVC_SAO_CRC = %x, count=%d\n", crc, count); |
| break; |
| } |
| count++; |
| old_crc = crc; |
| if (count > 100) { |
| pr_info("read HEVC_SAO_CRC = %x\n", crc); |
| count = 0; |
| } |
| } |
| } |
| |
| if (((udebug_pause_pos & 0xffff) |
| == (debug_tag & 0xffff)) && |
| (udebug_pause_decode_idx == 0 || |
| udebug_pause_decode_idx == dec->decode_idx) && |
| (udebug_pause_val == 0 || |
| udebug_pause_val == READ_HREG(DEBUG_REG2))) { |
| udebug_pause_pos &= 0xffff; |
| dec->ucode_pause_pos = udebug_pause_pos; |
| } |
| if (dec->ucode_pause_pos) |
| reset_process_time(dec); |
| else |
| WRITE_VREG(DEBUG_REG1, 0); |
| /*if (dec->dec_status) { |
| return IRQ_WAKE_THREAD; |
| } else*/ { |
| //dec->process_busy = 0; |
| } |
| } |
| } |
| |
| static irqreturn_t vavs3_isr_thread_fn(int irq, void *data) |
| { |
| struct AVS3Decoder_s *dec = (struct AVS3Decoder_s *)data; |
| DEC_CTX *ctx = &dec->avs3_dec.ctx; |
| unsigned int dec_status = dec->dec_status; |
| int i, ret; |
| int32_t start_code = 0; |
| #ifdef NEW_FB_CODE |
| struct avs3_decoder *avs3_dec = &dec->avs3_dec; |
| #endif |
| unsigned char avs3_bi_mid_ptr; |
| struct vdec_s *vdec = hw_to_vdec(dec); |
| |
| /*if (dec->wait_buf) |
| pr_info("set wait_buf to 0\r\n"); |
| */ |
| |
| #if 0 |
| avs3_print(dec, AVS3_DBG_BUFMGR_MORE, |
| "%s decode_status 0x%x process_state %d lcu 0x%x\n", |
| __func__, dec_status, dec->process_state, |
| READ_VREG(HEVC_PARSER_LCU_START)); |
| #else |
| if (debug & AVS3_DBG_IRQ_EVENT) { |
| if (dec->front_back_mode != 1) |
| avs3_print(dec, 0, |
| "avs3 isr dec status = 0x%x, debug_tag 0x%x, lcu 0x%x shiftbyte 0x%x (%x %x lev %x, wr %x, rd %x)\n", |
| dec_status, READ_HREG(DEBUG_REG1), READ_VREG(HEVC_PARSER_LCU_START), |
| READ_VREG(HEVC_SHIFT_BYTE_COUNT), |
| READ_VREG(HEVC_STREAM_START_ADDR), |
| READ_VREG(HEVC_STREAM_END_ADDR), |
| READ_VREG(HEVC_STREAM_LEVEL), |
| READ_VREG(HEVC_STREAM_WR_PTR), |
| READ_VREG(HEVC_STREAM_RD_PTR) |
| ); |
| else |
| avs3_print(dec, 0, |
| "avs3 isr dec status = 0x%x, debug_tag 0x%x, lcu 0x%x shiftbyte 0x%x (%x %x lev %x, wr %x, rd %x) [BE] pc %x psr %x DEC_STATUS %x\n", |
| dec_status, READ_HREG(DEBUG_REG1), READ_VREG(HEVC_PARSER_LCU_START), |
| READ_VREG(HEVC_SHIFT_BYTE_COUNT), |
| READ_VREG(HEVC_STREAM_START_ADDR), |
| READ_VREG(HEVC_STREAM_END_ADDR), |
| READ_VREG(HEVC_STREAM_LEVEL), |
| READ_VREG(HEVC_STREAM_WR_PTR), |
| READ_VREG(HEVC_STREAM_RD_PTR), |
| READ_VREG(HEVC_MPC_E_DBE), |
| READ_VREG(HEVC_MPSR_DBE), |
| READ_VREG(HEVC_DEC_STATUS_DBE) |
| ); |
| } |
| |
| if (udebug_flag) { |
| uint debug_tag = READ_HREG(DEBUG_REG1); |
| |
| if (debug_tag != 0) { |
| handle_ucode_dbg(dec, debug_tag); |
| //dec->process_busy = 0; |
| //return IRQ_HANDLED; |
| } |
| } |
| |
| #endif |
| |
| if ((dec_status == AVS3_HEAD_PIC_I_READY) || |
| (dec_status == AVS3_HEAD_PIC_PB_READY)) { |
| decoder_trace(dec->trace.decode_time_name, DECODER_ISR_THREAD_HEAD_START, TRACE_BASIC); |
| } else if (dec_status == HEVC_DECPIC_DATA_DONE) { |
| decoder_trace(dec->trace.decode_time_name, DECODER_ISR_THREAD_PIC_DONE_START, TRACE_BASIC); |
| } |
| |
| #ifndef G12A_BRINGUP_DEBUG |
| if (dec->eos) { |
| goto irq_handled_exit; |
| } |
| #endif |
| dec->wait_buf = 0; |
| if (dec_status == AVS3_DECODE_BUFEMPTY) { |
| if (dec->m_ins_flag) { |
| reset_process_time(dec); |
| if (!vdec_frame_based(hw_to_vdec(dec))) |
| dec_again_process(dec); |
| else { |
| dec->dec_result = DEC_RESULT_DONE; |
| reset_process_time(dec); |
| #ifdef NEW_FB_CODE |
| if (dec->front_back_mode == 1) { |
| amhevc_stop_f(); |
| } else |
| #endif |
| amhevc_stop(); |
| vdec_schedule_work(&dec->work); |
| } |
| } |
| goto irq_handled_exit; |
| } else if (dec_status == HEVC_DECPIC_DATA_DONE) { |
| mutex_lock(&dec->slice_header_lock); |
| mutex_unlock(&dec->slice_header_lock); |
| vdec->front_pic_done = true; |
| if (dec->front_back_mode == 0) { |
| avs3_print(dec, PRINT_FLAG_VDEC_STATUS, |
| "HEVC_DECPIC_DATA_DONE: decode_idx %d stream crc %x shiftcnt=0x%x, HEVC_SAO_CRC %x HEVC_SAO_MMU_STATUS %x\n", |
| dec->frame_count, |
| READ_VREG(HEVC_STREAM_CRC), |
| READ_VREG(HEVC_SHIFT_BYTE_COUNT), |
| READ_VREG(HEVC_SAO_CRC), |
| READ_VREG(HEVC_SAO_MMU_STATUS)); |
| |
| if (debug & AVS3_DBG_BUFMGR_DETAIL) { |
| pr_info("HEVC_CM_BODY_START_ADDR = %x\n", READ_VREG(HEVC_CM_BODY_START_ADDR)); |
| pr_info("HEVC_CM_HEADER_START_ADDR = %x\n", READ_VREG(HEVC_CM_HEADER_START_ADDR)); |
| pr_info("HEVC_SAO_Y_START_ADDR = %x\n", READ_VREG(HEVC_SAO_Y_START_ADDR)); |
| pr_info("HEVC_SAO_Y_LENGTH = %x\n", READ_VREG(HEVC_SAO_Y_LENGTH)); |
| pr_info("HEVC_SAO_C_START_ADDR = %x\n", READ_VREG(HEVC_SAO_C_START_ADDR)); |
| pr_info("HEVC_SAO_C_LENGTH = %x\n", READ_VREG(HEVC_SAO_C_LENGTH)); |
| pr_info("HEVC_SAO_Y_WPTR = %x\n", READ_VREG(HEVC_SAO_Y_WPTR)); |
| pr_info("HEVC_SAO_C_WPTR = %x\n", READ_VREG(HEVC_SAO_C_WPTR)); |
| |
| pr_info("HEVC_SAO_CTRL0 = %x\n", READ_VREG(HEVC_SAO_CTRL0)); |
| pr_info("HEVC_SAO_CTRL1 = %x\n", READ_VREG(HEVC_SAO_CTRL1)); |
| pr_info("HEVC_SAO_CTRL2 = %x\n", READ_VREG(HEVC_SAO_CTRL2)); |
| pr_info("HEVC_SAO_CTRL3 = %x\n", READ_VREG(HEVC_SAO_CTRL3)); |
| pr_info("HEVC_SAO_CTRL4 = %x\n", READ_VREG(HEVC_SAO_CTRL4)); |
| pr_info("HEVC_SAO_CTRL5 = %x\n", READ_VREG(HEVC_SAO_CTRL5)); |
| |
| } |
| if ((debug & AVS3_DBG_NOT_RECYCLE_MMU_TAIL) == 0) |
| avs3_recycle_mmu_buf_tail(dec); |
| } else { |
| struct avs3_frame_s *pic = dec->avs3_dec.cur_pic; |
| avs3_print(dec, PRINT_FLAG_VDEC_STATUS, |
| "FrontEnd data done %d, fb_rd_pos %d, pic index %d, stream crc %x shiftbyte %x\n", |
| avs3_dec->frontend_decoded_count, avs3_dec->fb_rd_pos, pic->index, |
| READ_VREG(HEVC_STREAM_CRC), READ_VREG(HEVC_SHIFT_BYTE_COUNT)); |
| } |
| |
| dec->start_decoding_flag |= 0x3; |
| if (dec->m_ins_flag) { |
| set_cuva_data(dec); |
| update_decoded_pic(dec); |
| #ifdef NEW_FB_CODE |
| if (dec->front_back_mode == 0) |
| #endif |
| get_picture_qos_info(dec); |
| reset_process_time(dec); |
| dec->dec_result = DEC_RESULT_DONE; |
| #ifdef NEW_FB_CODE |
| if (dec->front_back_mode) { |
| /*simulation code: if (dec_status == HEVC_DECPIC_DATA_DONE) {*/ |
| front_decpic_done_update(dec, 1); /*not multi pictures in one packe*/ |
| } else |
| #endif |
| amhevc_stop(); |
| decoder_trace(dec->trace.decode_time_name, DECODER_ISR_THREAD_EDN, TRACE_BASIC); |
| avs3_work_implement(dec); |
| } |
| |
| goto irq_handled_exit; |
| } |
| #if 0 |
| if (dec_status == AVS3_EOS) { |
| if (dec->m_ins_flag) |
| reset_process_time(dec); |
| |
| avs3_print(dec, AVS3_DBG_BUFMGR, |
| "AVS3_EOS, flush buffer\r\n"); |
| |
| avs3_post_process(&dec->avs3_dec); |
| avs3_prepare_display_buf(dec); |
| |
| avs3_print(dec, AVS3_DBG_BUFMGR, |
| "send AVS3_10B_DISCARD_NAL\r\n"); |
| WRITE_VREG(HEVC_DEC_STATUS_REG, AVS3_10B_DISCARD_NAL); |
| if (dec->m_ins_flag) { |
| update_decoded_pic(dec); |
| dec->dec_result = DEC_RESULT_DONE; |
| amhevc_stop(); |
| vdec_schedule_work(&dec->work); |
| } |
| goto irq_handled_exit; |
| } else |
| #endif |
| if (dec_status == AVS3_DECODE_OVER_SIZE) { |
| avs3_print(dec, 0, |
| "avs3 decode oversize !!\n"); |
| debug |= (AVS3_DBG_DIS_LOC_ERROR_PROC | |
| AVS3_DBG_DIS_SYS_ERROR_PROC); |
| dec->fatal_error |= DECODER_FATAL_ERROR_SIZE_OVERFLOW; |
| if (dec->m_ins_flag) |
| reset_process_time(dec); |
| goto irq_handled_exit; |
| } |
| |
| if (dec->m_ins_flag) |
| reset_process_time(dec); |
| |
| if (dec_status == AVS3_HEAD_SEQ_READY) |
| start_code = SEQUENCE_HEADER_CODE; |
| else if (dec_status == AVS3_HEAD_PIC_I_READY) |
| start_code = I_PICTURE_START_CODE; |
| else if (dec_status == AVS3_HEAD_PIC_PB_READY) |
| start_code = PB_PICTURE_START_CODE; |
| else if (dec_status == AVS3_HEAD_SEQ_END_READY) |
| start_code = SEQUENCE_END_CODE; |
| else if (dec_status == AVS3_STARTCODE_SEARCH_DONE) |
| /*VIDEO_EDIT_CODE*/ |
| start_code = READ_VREG(CUR_NAL_UNIT_TYPE); |
| else |
| goto irq_handled_exit; |
| if (dec->process_state == |
| PROC_STATE_HEAD_AGAIN |
| ) { |
| if ((start_code == I_PICTURE_START_CODE) |
| || (start_code == PB_PICTURE_START_CODE)) { |
| avs3_print(dec, 0, |
| "PROC_STATE_HEAD_AGAIN error, start_code 0x%x!!!\r\n", |
| start_code); |
| goto irq_handled_exit; |
| } else { |
| avs3_print(dec, AVS3_DBG_BUFMGR, |
| "PROC_STATE_HEAD_AGAIN, start_code 0x%x\r\n", |
| start_code); |
| dec->process_state = PROC_STATE_HEAD_DONE; |
| WRITE_VREG(HEVC_DEC_STATUS_REG, AVS3_ACTION_DONE); |
| goto irq_handled_exit; |
| } |
| } else if (dec->process_state == |
| PROC_STATE_DECODE_AGAIN) { |
| if ((start_code == I_PICTURE_START_CODE) |
| || (start_code == PB_PICTURE_START_CODE)) { |
| avs3_print(dec, AVS3_DBG_BUFMGR, |
| "PROC_STATE_DECODE_AGAIN=> decode_slice, start_code 0x%x\r\n", |
| start_code); |
| if ((dec->front_back_mode == 1) && (dec->pic_list_init_flag == 0) && (dec->pic_list_wait_alloc_done_flag == BUFFER_ALLOCATE_DONE)) { |
| dec->pic_list_init_flag = 1; |
| goto alloc_buffer_done; |
| } |
| else |
| goto decode_slice; |
| } else { |
| avs3_print(dec, 0, |
| "PROC_STATE_DECODE_AGAIN, start_code 0x%x!!!\r\n", |
| start_code); |
| WRITE_VREG(HEVC_DEC_STATUS_REG, AVS3_ACTION_DONE); |
| goto irq_handled_exit; |
| } |
| } |
| |
| if ((start_code == I_PICTURE_START_CODE) |
| || (start_code == PB_PICTURE_START_CODE) |
| || (start_code == SEQUENCE_END_CODE) |
| || (start_code == VIDEO_EDIT_CODE)) { |
| |
| if (dec->avs3_dec.cur_pic != NULL) { |
| #ifndef NEW_FB_CODE |
| int32_t ii; |
| #endif |
| check_pic_error(dec, dec->avs3_dec.cur_pic); |
| if (debug & AVS3_DBG_PRINT_PIC_LIST) |
| print_pic_pool(avs3_dec, "before post process"); |
| avs3_bufmgr_post_process(avs3_dec); |
| |
| if (debug & AVS3_DBG_PRINT_PIC_LIST) |
| print_pic_pool(&dec->avs3_dec, "after post_process"); |
| |
| if ((dec->front_back_mode != 1) || !efficiency_mode) |
| avs3_prepare_display_buf(dec); |
| dec->avs3_dec.cur_pic = NULL; |
| #ifdef NEW_FB_CODE |
| //release_free_mmu_buffers(dec); |
| #else |
| #endif |
| } |
| } |
| |
| if ((dec_status == AVS3_HEAD_PIC_I_READY) |
| || (dec_status == AVS3_HEAD_PIC_PB_READY)) { |
| |
| if (debug & AVS3_DBG_SEND_PARAM_WITH_REG) { |
| get_rpm_param( |
| &dec->avs3_dec.param); |
| } else { |
| decoder_trace(dec->trace.decode_header_memory_time_name, TRACE_HEADER_RPM_START, TRACE_BASIC); |
| for (i = 0; i < (RPM_VALID_END - RPM_BEGIN); i += 4) { |
| int ii; |
| for (ii = 0; ii < 4; ii++) |
| dec->avs3_dec.param.l.data[i + ii] = |
| dec->rpm_ptr[i + 3 - ii]; |
| } |
| decoder_trace(dec->trace.decode_header_memory_time_name, TRACE_HEADER_RPM_END, TRACE_BASIC); |
| } |
| #if 0 //def SANITY_CHECK |
| if (dec->avs3_dec.param.p.num_of_ref_cur > |
| dec->avs3_dec.ref_maxbuffer) { |
| pr_info("Warning: Wrong num_of_ref_cur %d, force to %d\n", |
| dec->avs3_dec.param.p.num_of_ref_cur, |
| dec->avs3_dec.ref_maxbuffer); |
| dec->avs3_dec.param.p.num_of_ref_cur = |
| dec->avs3_dec.ref_maxbuffer; |
| } |
| #endif |
| |
| debug_buffer_mgr_more(dec); |
| get_frame_rate(&dec->avs3_dec.param, dec); |
| |
| if (dec->avs3_dec.param.p.video_signal_type |
| & (1<<30)) { |
| union param_u *pPara; |
| |
| avs3_print(dec, 0, |
| "avs3 HDR meta data present\n"); |
| pPara = &dec->avs3_dec.param; |
| |
| /*clean this flag*/ |
| pPara->p.video_signal_type |
| &= ~(1<<30); |
| |
| dec->vf_dp.present_flag = 1; |
| |
| dec->vf_dp.white_point[0] |
| = pPara->p.white_point_x; |
| avs3_print(dec, AVS3_DBG_HDR_INFO, |
| "white_point[0]:0x%x\n", |
| dec->vf_dp.white_point[0]); |
| |
| dec->vf_dp.white_point[1] |
| = pPara->p.white_point_y; |
| avs3_print(dec, AVS3_DBG_HDR_INFO, |
| "white_point[1]:0x%x\n", |
| dec->vf_dp.white_point[1]); |
| |
| for (i = 0; i < 3; i++) { |
| dec->vf_dp.primaries[i][0] |
| = pPara->p.display_primaries_x[i]; |
| avs3_print(dec, AVS3_DBG_HDR_INFO, |
| "primaries[%d][0]:0x%x\n", |
| i, |
| dec->vf_dp.primaries[i][0]); |
| } |
| |
| for (i = 0; i < 3; i++) { |
| dec->vf_dp.primaries[i][1] |
| = pPara->p.display_primaries_y[i]; |
| avs3_print(dec, AVS3_DBG_HDR_INFO, |
| "primaries[%d][1]:0x%x\n", |
| i, |
| dec->vf_dp.primaries[i][1]); |
| } |
| |
| dec->vf_dp.luminance[0] |
| = pPara->p.max_display_mastering_luminance; |
| avs3_print(dec, AVS3_DBG_HDR_INFO, |
| "luminance[0]:0x%x\n", |
| dec->vf_dp.luminance[0]); |
| |
| dec->vf_dp.luminance[1] |
| = pPara->p.min_display_mastering_luminance; |
| avs3_print(dec, AVS3_DBG_HDR_INFO, |
| "luminance[1]:0x%x\n", |
| dec->vf_dp.luminance[1]); |
| |
| dec->vf_dp.content_light_level.present_flag |
| = 1; |
| dec->vf_dp.content_light_level.max_content |
| = pPara->p.max_content_light_level; |
| avs3_print(dec, AVS3_DBG_HDR_INFO, |
| "max_content:0x%x\n", |
| dec->vf_dp.content_light_level.max_content); |
| |
| dec->vf_dp.content_light_level.max_pic_average |
| = pPara->p.max_picture_average_light_level; |
| |
| avs3_print(dec, AVS3_DBG_HDR_INFO, |
| "max_pic_average:0x%x\n", |
| dec->vf_dp.content_light_level.max_pic_average); |
| } |
| if (dec->video_ori_signal_type != |
| ((dec->avs3_dec.param.p.video_signal_type << 16) |
| | dec->avs3_dec.param.p.color_description)) { |
| u32 v = dec->avs3_dec.param.p.video_signal_type; |
| u32 c = dec->avs3_dec.param.p.color_description; |
| u32 convert_c = c; |
| |
| if (v & 0x2000) { |
| avs3_print(dec, AVS3_DBG_HDR_INFO, |
| "video_signal_type present:\n"); |
| avs3_print(dec, AVS3_DBG_HDR_INFO, |
| " %s %s\n", |
| video_format_names[(v >> 10) & 7], |
| ((v >> 9) & 1) ? |
| "full_range" : "limited"); |
| if (v & 0x100) { |
| u32 transfer; |
| u32 maxtrix; |
| |
| avs3_print(dec, AVS3_DBG_HDR_INFO, |
| "color_description present:\n"); |
| avs3_print(dec, AVS3_DBG_HDR_INFO, |
| "color_primarie = %d\n", |
| v & 0xff); |
| avs3_print(dec, AVS3_DBG_HDR_INFO, |
| "transfer_characteristic = %d\n", |
| (c >> 8) & 0xff); |
| avs3_print(dec, AVS3_DBG_HDR_INFO, |
| " matrix_coefficient = %d\n", |
| c & 0xff); |
| |
| transfer = (c >> 8) & 0xFF; |
| if (transfer >= 15) |
| avs3_print(dec, AVS3_DBG_HDR_INFO, |
| "unsupport transfer_characteristic\n"); |
| else if (transfer == 14) |
| transfer = 18; /* HLG */ |
| else if (transfer == 13) |
| transfer = 32; |
| else if (transfer == 12) |
| transfer = 16; |
| else if (transfer == 11) |
| transfer = 15; |
| |
| maxtrix = c & 0xFF; |
| if (maxtrix >= 10) |
| avs3_print(dec, AVS3_DBG_HDR_INFO, |
| "unsupport matrix_coefficient\n"); |
| else if (maxtrix == 9) |
| maxtrix = 10; |
| else if (maxtrix == 8) |
| maxtrix = 9; |
| |
| convert_c = (transfer << 8) | (maxtrix); |
| |
| avs3_print(dec, AVS3_DBG_HDR_INFO, |
| " convered c:0x%x\n", |
| convert_c); |
| } |
| } |
| |
| if (enable_force_video_signal_type) |
| dec->video_signal_type |
| = force_video_signal_type; |
| else { |
| dec->video_signal_type |
| = (v << 16) | convert_c; |
| |
| dec->video_ori_signal_type |
| = (v << 16) | c; |
| } |
| |
| video_signal_type = dec->video_signal_type; |
| } |
| } |
| |
| #if 0 |
| if ((debug_again & 0x4) && |
| dec->process_state == |
| PROC_STATE_INIT) { |
| if (start_code == PB_PICTURE_START_CODE) { |
| dec->process_state = PROC_STATE_TEST1; |
| dec_again_process(dec); |
| goto irq_handled_exit; |
| } |
| } |
| #endif |
| |
| if (start_code == SEQUENCE_HEADER_CODE) { |
| avs3_print(dec, AVS3_DBG_BUFMGR_MORE, |
| " ## SEQUENCE_HEADER_CODE ##\n"); |
| dec->avs3_dec.seq_change_flag = 1; |
| dec->avs3_dec.init_hw_flag = 0; |
| } |
| |
| if (dec->has_i_frame == 0 && |
| start_code == PB_PICTURE_START_CODE) { |
| dec->dec_result = DEC_RESULT_DONE; |
| #ifdef NEW_FB_CODE |
| if (dec->front_back_mode == 1) |
| amhevc_stop_f(); |
| else |
| #endif |
| amhevc_stop(); |
| avs3_print(dec, 0, "no i frame!!\n"); |
| vdec_schedule_work(&dec->work); |
| goto irq_handled_exit; |
| } |
| |
| mutex_lock(&dec->slice_header_lock); |
| if (start_code == SEQUENCE_END_CODE) { |
| avs3_bufmgr_process(&dec->avs3_dec, SEQUENCE_END_CODE); |
| WRITE_VREG(HEVC_DEC_STATUS_REG, AVS3_ACTION_DONE); |
| } else if (start_code == SEQUENCE_HEADER_CODE || |
| start_code == VIDEO_EDIT_CODE) { |
| /*if (dec->m_ins_flag && |
| vdec_frame_based(hw_to_vdec(dec))) |
| dec->start_decoding_flag |= 0x1;*/ |
| dec->process_state = PROC_STATE_HEAD_DONE; |
| WRITE_VREG(HEVC_DEC_STATUS_REG, AVS3_ACTION_DONE); |
| } else if (start_code == I_PICTURE_START_CODE || |
| start_code == PB_PICTURE_START_CODE) { |
| avs3_frame_t *cur_pic; |
| ret = 0; |
| #ifdef NEW_FB_CODE |
| if (dec->m_ins_flag) { |
| u32 width = avs3_dec->param.p.sqh_horizontal_size; |
| u32 height = avs3_dec->param.p.sqh_vertical_size; |
| u8 bit_depth = (u8)avs3_dec->param.p.sqh_encoding_precision; |
| int cur_mmu_fb_4k_number = 0; |
| |
| width = ((width + MINI_SIZE - 1) >> MINI_SIZE_LOG2) << MINI_SIZE_LOG2; |
| height = ((height + MINI_SIZE - 1) >> MINI_SIZE_LOG2) << MINI_SIZE_LOG2; |
| bit_depth = (bit_depth == 2) ? 10 : 8; |
| cur_mmu_fb_4k_number = dec->fb_ifbuf_num * avs3_mmu_page_num(dec, |
| width, height, (bit_depth == 10)); |
| |
| if ((dec->front_back_mode == 1) && |
| (start_code == I_PICTURE_START_CODE) && |
| (dec->mmu_fb_4k_number < cur_mmu_fb_4k_number) && |
| (cur_mmu_fb_4k_number > 0)) { |
| amhevc_stop_f(); |
| avs3_print(dec, AVS3_DBG_BUFMGR, "need realloc mmu fb\n"); |
| uninit_mmu_fb_bufstate(dec); |
| init_mmu_fb_bufstate(dec, cur_mmu_fb_4k_number); |
| dec_again_process(dec); |
| mutex_unlock(&dec->slice_header_lock); |
| goto irq_handled_exit; |
| } |
| } |
| #endif |
| |
| avs3_print(dec, AVS3_DBG_BUFMGR, "========== Picture %d\n", avs3_dec->decode_id++); |
| //avs3_dec->ins_offset = 0; //move to init_pic_list_hw_fb |
| if (debug & AVS3_DBG_PRINT_PIC_LIST) |
| print_pic_pool(avs3_dec, "before bufmgr process"); |
| if (is_avs3_print_param()) { |
| print_param(&avs3_dec->param); |
| print_alf_param(&avs3_dec->param); |
| } |
| |
| decoder_trace(dec->trace.decode_header_memory_time_name, 9, TRACE_BASIC); |
| |
| if (avs3_dec->seq_change_flag) { |
| avs3_bufmgr_process(avs3_dec, SEQUENCE_HEADER_CODE); |
| avs3_dec->seq_change_flag = 0; |
| } |
| ret = avs3_bufmgr_process(avs3_dec, start_code); |
| if (debug & AVS3_DBG_PRINT_PIC_LIST) |
| print_pic_pool(avs3_dec, "after bufmgr process"); |
| |
| |
| if ((ret == 0) && (avs3_dec->cur_pic != NULL)) { |
| cur_pic = avs3_dec->cur_pic; |
| #ifdef NEW_FRONT_BACK_CODE |
| cur_pic->width = avs3_dec->img.width; |
| cur_pic->height = avs3_dec->img.height; |
| cur_pic->depth = avs3_dec->input.sample_bit_depth; |
| #endif |
| |
| if (!dec->m_ins_flag) |
| dec->slice_idx++; |
| else |
| release_cuva_data(cur_pic); |
| } |
| |
| #if 0 |
| if (avs3_dec->init_hw_flag == 0) { |
| //from simulation |
| init_pic_list_hw(avs3_dec, buf_spec, mc_buf_spec); |
| avs3_dec->init_hw_flag = 1; |
| } |
| #else |
| if (dec->pic_list_init_flag == 0) { |
| int32_t lcu_size_log2 = avs3_dec->lcu_size_log2; |
| |
| if ((dec->front_back_mode == 1) && (paral_alloc_buffer_mode & 1)) { |
| if ((dec->pic_list_wait_alloc_done_flag == BUFFER_INIT)) { |
| dec->dec_result = DEC_RESULT_WAIT_BUFFER; |
| avs3_print(dec, AVS3_DBG_BUFMGR, "alloc buffer\n"); |
| vdec_schedule_work(&dec->work); |
| mutex_unlock(&dec->slice_header_lock); |
| goto irq_handled_exit; |
| } |
| } else |
| init_pic_list(dec, lcu_size_log2); |
| |
| #ifdef NEW_FB_CODE |
| if ((dec->front_back_mode == 1) || |
| (dec->front_back_mode == 3)) |
| init_pic_list_hw_fb(dec); |
| else |
| #endif |
| init_pic_list_hw(dec); |
| #endif |
| dec->pic_list_init_flag = 1; |
| } |
| |
| decoder_trace(dec->trace.decode_header_memory_time_name, 10, TRACE_BASIC); |
| alloc_buffer_done: |
| |
| #ifdef I_ONLY_SUPPORT |
| if ((start_code == PB_PICTURE_START_CODE) && |
| (dec->i_only & 0x2)) |
| ret = -2; |
| #endif |
| |
| if (ret == 0) { |
| #ifdef AVS3_10B_MMU |
| if (dec->mmu_enable |
| #ifdef NEW_FB_CODE |
| && (dec->front_back_mode != 1) |
| #endif |
| ) { |
| #if 0 |
| //DDD |
| if (cur_pic->index == -1) { |
| pr_info("dec->avs3_dec.ctx.pic %p\n", dec->avs3_dec.ctx.pic); |
| print_pic_pool(avs3_dec, "error"); |
| } |
| #endif |
| ret = avs3_alloc_mmu(dec, |
| cur_pic->index, |
| cur_pic->width, |
| cur_pic->height, |
| cur_pic->depth, |
| dec->frame_mmu_map_addr); |
| if (ret >= 0) { |
| dec->cur_fb_idx_mmu = |
| cur_pic->index; |
| cur_pic->mmu_alloc_flag = 1; |
| } else |
| pr_err("can't alloc need mmu1,idx %d ret =%d\n", |
| cur_pic->index, |
| ret); |
| } |
| #endif |
| #ifdef AVS3_10B_MMU_DW |
| if (dec->dw_mmu_enable |
| #ifdef NEW_FB_CODE |
| && (dec->front_back_mode != 1) |
| #endif |
| ) { |
| ret = avs3_alloc_dw_mmu(dec, |
| cur_pic->index, |
| cur_pic->width, |
| cur_pic->height, |
| cur_pic->depth, |
| dec->dw_frame_mmu_map_addr); |
| if (ret >= 0) { |
| dec->cur_fb_idx_mmu = |
| cur_pic->index; |
| cur_pic->mmu_alloc_flag = 1; |
| } else |
| pr_err("can't alloc need dw mmu1,idx %d ret =%d\n", |
| dec->avs3_dec.cur_pic->index, |
| ret); |
| } |
| #endif |
| } |
| |
| #ifndef MV_USE_FIXED_BUF |
| decoder_trace(dec->trace.decode_header_memory_time_name, TRACE_HEADER_MEMORY_START, TRACE_BASIC); |
| |
| if (ret == 0 && cur_pic-> |
| mpred_mv_wr_start_addr == 0 |
| #if 0 //def NEW_FB_CODE |
| && (dec->front_back_mode != 1) |
| #endif |
| ) { |
| unsigned long buf_addr; |
| unsigned mv_buf_size = get_mv_buf_size( |
| dec, |
| cur_pic->width, |
| cur_pic->height); |
| int i = cur_pic->index; |
| /*if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) |
| mv_buf_size = 0x120000 * 4;*/ |
| if (decoder_bmmu_box_alloc_buf_phy |
| (dec->bmmu_box, |
| MV_BUFFER_IDX(i), |
| mv_buf_size, |
| DRIVER_NAME, |
| &buf_addr) < 0) { |
| ret = -1; |
| } else { |
| cur_pic-> |
| mpred_mv_wr_start_addr |
| = buf_addr; |
| if (!vdec_secure(hw_to_vdec(dec))) |
| codec_mm_memset(cur_pic->mpred_mv_wr_start_addr, |
| 0, mv_buf_size); |
| } |
| } |
| |
| decoder_trace(dec->trace.decode_header_memory_time_name, TRACE_HEADER_MEMORY_END, TRACE_BASIC); |
| #endif |
| if (ret) { |
| avs3_print(dec, AVS3_DBG_BUFMGR, |
| "avs3_bufmgr_process=> %d, AVS3_10B_DISCARD_NAL\r\n", |
| ret); |
| WRITE_VREG(HEVC_DEC_STATUS_REG, AVS3_10B_DISCARD_NAL); |
| #ifdef AVS3_10B_MMU |
| if (dec->mmu_enable |
| #ifdef NEW_FB_CODE |
| && (dec->front_back_mode != 1) |
| #endif |
| ) |
| avs3_recycle_mmu_buf(dec); |
| #endif |
| if (dec->m_ins_flag) { |
| dec->dec_result = DEC_RESULT_DONE; |
| |
| vdec_schedule_work(&dec->work); |
| } |
| mutex_unlock(&dec->slice_header_lock); |
| goto irq_handled_exit; |
| } else { |
| |
| dec->avs3_dec.cur_pic->stream_offset = |
| READ_VREG(HEVC_SHIFT_BYTE_COUNT); |
| /* |
| struct PIC_BUFFER_CONFIG_s *cur_pic |
| = &cm->cur_frame->buf; |
| cur_pic->decode_idx = dec->frame_count; |
| */ |
| if (!dec->m_ins_flag) { |
| dec->frame_count++; |
| decode_frame_count[dec->index] |
| = dec->frame_count; |
| } |
| /*MULTI_INSTANCE_SUPPORT*/ |
| if (dec->chunk) { |
| dec->avs3_dec.cur_pic->pts = |
| dec->chunk->pts; |
| dec->avs3_dec.cur_pic->pts64 = |
| dec->chunk->pts64; |
| } |
| /**/ |
| decode_slice: |
| dec->avs3_dec.cur_pic->double_write_mode |
| = get_double_write_mode(dec); |
| |
| decoder_trace(dec->trace.decode_header_memory_time_name, TRACE_HEADER_REGISTER_START, TRACE_BASIC); |
| #ifdef NEW_FB_CODE |
| if (dec->front_back_mode == 1 || dec->front_back_mode == 3) { |
| if (!efficiency_mode) { |
| config_mc_buffer_fb(dec); |
| config_mcrcc_axi_hw_fb(dec); |
| } |
| |
| config_mpred_hw_fb(dec); |
| |
| if (!efficiency_mode) { |
| config_dblk_hw_fb(dec); |
| config_sao_hw_fb(dec); |
| config_alf_hw_fb(dec); |
| } |
| } else { |
| #endif |
| config_mc_buffer(dec); |
| #ifdef NEW_FB_CODE |
| if (dec->front_back_mode == 0) |
| #endif |
| config_mcrcc_axi_hw(dec); |
| config_mpred_hw(dec); |
| config_dblk_hw(dec); |
| config_sao_hw(dec); |
| config_alf_hw(dec); |
| #ifdef NEW_FB_CODE |
| } |
| #endif |
| decoder_trace(dec->trace.decode_header_memory_time_name, TRACE_HEADER_REGISTER_END, TRACE_BASIC); |
| |
| // HEVC_PARSER_HEADER_INFO : |
| // bit[30] -- avs3_bi_mid_ptr // (ctx->ptr - ctx->refp[0][REFP_0].ptr == ctx->refp[0][REFP_1].ptr - ctx->ptr) |
| // bit[21:16] -- ctx->dpm.num_refp[REFP_1] |
| // bit[15:10] -- ctx->dpm.num_refp[REFP_0] |
| avs3_bi_mid_ptr = (ctx->ptr - ctx->refp[0][REFP_0].ptr == ctx->refp[0][REFP_1].ptr - ctx->ptr); |
| WRITE_VREG(HEVC_PARSER_HEADER_INFO, (ctx->dpm.num_refp[REFP_0]<<10) | (ctx->dpm.num_refp[REFP_1]<<16) | (avs3_bi_mid_ptr<<30)); |
| |
| #ifdef BUFMGR_ONLY |
| WRITE_VREG(NAL_SEARCH_CTL, 0x1); |
| #else |
| WRITE_VREG(NAL_SEARCH_CTL, 0); |
| #endif |
| |
| #ifdef NEW_FRONT_BACK_CODE |
| if ((!efficiency_mode) && (dec->front_back_mode == 1 || |
| dec->front_back_mode == 3)) { |
| |
| WRITE_BACK_RET(avs3_dec); |
| avs3_print(dec, AVS3_DBG_BUFMGR_MORE, |
| "write system instruction, ins_offset = %d, addr = 0x%x\n", |
| avs3_dec->ins_offset, avs3_dec->fr.sys_imem_ptr); |
| |
| avs3_dec->sys_imem_ptr = avs3_dec->fr.sys_imem_ptr; |
| avs3_dec->sys_imem_ptr_v = avs3_dec->fr.sys_imem_ptr_v; |
| |
| #ifdef LARGE_INSTRUCTION_SPACE_SUPORT |
| if (avs3_dec->ins_offset > 512) { |
| avs3_print(dec, 0, |
| "!!!!!Error!!!!!!!!, ins_offset %d is too big (>512)\n", avs3_dec->ins_offset); |
| avs3_dec->ins_offset = 512; |
| } else if (avs3_dec->ins_offset < 256) { |
| avs3_dec->ins_offset = 256; |
| WRITE_BACK_RET(avs3_dec); |
| } |
| |
| memcpy(avs3_dec->sys_imem_ptr_v, (void*)(&avs3_dec->instruction[0]), avs3_dec->ins_offset*4); |
| //copyToDDR_32bits(dec->fr.sys_imem_ptr, instruction, ins_offset*4, 0); |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, |
| "cur_imem_ptr_v 0x%x: %02x %02x %02x %02x\n", |
| avs3_dec->sys_imem_ptr_v, |
| ((u8 *)avs3_dec->sys_imem_ptr_v)[0], ((u8 *)avs3_dec->sys_imem_ptr_v)[1], |
| ((u8 *)avs3_dec->sys_imem_ptr_v)[2], ((u8 *)avs3_dec->sys_imem_ptr_v)[3]); |
| avs3_dec->sys_imem_ptr += 2 * FB_IFBUF_SYS_IMEM_BLOCK_SIZE; |
| avs3_dec->sys_imem_ptr_v += 2 * FB_IFBUF_SYS_IMEM_BLOCK_SIZE; |
| #else |
| if (avs3_dec->ins_offset > 256) { |
| avs3_print(dec, 0, |
| "!!!!!Error!!!!!!!!, ins_offset %d is too big (>256)\n", avs3_dec->ins_offset); |
| avs3_dec->ins_offset = 256; |
| } |
| |
| memcpy(avs3_dec->sys_imem_ptr_v, (void*)(&avs3_dec->instruction[0]), avs3_dec->ins_offset*4); |
| //copyToDDR_32bits(dec->fr.sys_imem_ptr, instruction, ins_offset*4, 0); |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, |
| "cur_imem_ptr_v 0x%x: %02x %02x %02x %02x\n", |
| avs3_dec->sys_imem_ptr_v, |
| ((u8 *)avs3_dec->sys_imem_ptr_v)[0], ((u8 *)avs3_dec->sys_imem_ptr_v)[1], |
| ((u8 *)avs3_dec->sys_imem_ptr_v)[2], ((u8 *)avs3_dec->sys_imem_ptr_v)[3]); |
| avs3_dec->sys_imem_ptr += FB_IFBUF_SYS_IMEM_BLOCK_SIZE; |
| avs3_dec->sys_imem_ptr_v +=FB_IFBUF_SYS_IMEM_BLOCK_SIZE; |
| #endif |
| if (avs3_dec->sys_imem_ptr >= avs3_dec->fb_buf_sys_imem.buf_end) { |
| avs3_print(dec, AVS3_DBG_BUFMGR, |
| "sys_imem_ptr is 0x%x, wrap around\n", avs3_dec->sys_imem_ptr); |
| avs3_dec->sys_imem_ptr = avs3_dec->fb_buf_sys_imem.buf_start; |
| avs3_dec->sys_imem_ptr_v = avs3_dec->fb_buf_sys_imem_addr; |
| } |
| if (dec->front_back_mode == 1) { |
| //WRITE_VREG(HEVC_ASSIST_RING_F_INDEX, 8); |
| //WRITE_VREG(HEVC_ASSIST_RING_F_WPTR, sys_imem_ptr); |
| //imem_count++; |
| WRITE_VREG(DOS_HEVC_STALL_START, 0); // disable stall |
| } |
| |
| WRITE_VREG(HEVC_DEC_STATUS_REG, AVS3_ACTION_DONE); |
| } else { |
| WRITE_VREG(HEVC_DEC_STATUS_REG, AVS3_ACTION_DONE); |
| } |
| #endif |
| |
| //WRITE_VREG(HEVC_DEC_STATUS_REG, AVS3_ACTION_DONE); |
| //pr_info("!!write AVS3_ACTION_DONE %d\n", __LINE__); |
| |
| if ((debug_again & 0x2) && |
| dec->process_state == |
| PROC_STATE_INIT) { |
| dec->process_state = PROC_STATE_DECODING; |
| dec_again_process(dec); |
| mutex_unlock(&dec->slice_header_lock); |
| goto irq_handled_exit; |
| } |
| |
| dec->process_state = PROC_STATE_DECODING; |
| |
| } |
| if (start_code == I_PICTURE_START_CODE) |
| dec->has_i_frame = 1; |
| if (dec->m_ins_flag) |
| start_process_time(dec); |
| } |
| vdec_profile(hw_to_vdec(dec), VDEC_PROFILE_DECODER_START, CORE_MASK_HEVC); |
| |
| if ((dec_status == AVS3_HEAD_PIC_I_READY) || |
| (dec_status == AVS3_HEAD_PIC_PB_READY)) { |
| decoder_trace(dec->trace.decode_time_name, DECODER_ISR_THREAD_HEAD_END, TRACE_PERFORMANCE_DETAIL); |
| } |
| if (efficiency_mode && (dec->front_back_mode == 1)) { |
| if (dec->pic_list_init_flag) { |
| #ifdef NEW_FB_CODE |
| if ((dec->front_back_mode == 1) || |
| (dec->front_back_mode == 3)) |
| init_pic_list_hw_fb(dec); |
| else |
| #endif |
| init_pic_list_hw(dec); |
| } |
| |
| if ((dec->front_back_mode == 1 || dec->front_back_mode == 3) && |
| (start_code == I_PICTURE_START_CODE || |
| start_code == PB_PICTURE_START_CODE)) { |
| config_mc_buffer_fb(dec); |
| config_mcrcc_axi_hw_fb(dec); |
| config_dblk_hw_fb(dec); |
| config_sao_hw_fb(dec); |
| config_alf_hw_fb(dec); |
| |
| WRITE_BACK_RET(avs3_dec); |
| avs3_print(dec, AVS3_DBG_BUFMGR_MORE, |
| "write system instruction, ins_offset = %d, addr = 0x%x\n", |
| avs3_dec->ins_offset, avs3_dec->fr.sys_imem_ptr); |
| |
| avs3_dec->sys_imem_ptr = avs3_dec->fr.sys_imem_ptr; |
| avs3_dec->sys_imem_ptr_v = avs3_dec->fr.sys_imem_ptr_v; |
| #ifdef LARGE_INSTRUCTION_SPACE_SUPORT |
| if (avs3_dec->ins_offset > 512) { |
| avs3_print(dec, 0, |
| "!!!!!Error!!!!!!!!, ins_offset %d is too big (>512)\n", avs3_dec->ins_offset); |
| avs3_dec->ins_offset = 512; |
| } else if (avs3_dec->ins_offset < 256) { |
| avs3_dec->ins_offset = 256; |
| WRITE_BACK_RET(avs3_dec); |
| } |
| memcpy(avs3_dec->sys_imem_ptr_v, (void*)(&avs3_dec->instruction[0]), avs3_dec->ins_offset*4); |
| //copyToDDR_32bits(dec->fr.sys_imem_ptr, instruction, ins_offset*4, 0); |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, |
| "cur_imem_ptr_v 0x%x: %02x %02x %02x %02x\n", |
| avs3_dec->sys_imem_ptr_v, |
| ((u8 *)avs3_dec->sys_imem_ptr_v)[0], ((u8 *)avs3_dec->sys_imem_ptr_v)[1], |
| ((u8 *)avs3_dec->sys_imem_ptr_v)[2], ((u8 *)avs3_dec->sys_imem_ptr_v)[3]); |
| |
| avs3_dec->sys_imem_ptr += 2*FB_IFBUF_SYS_IMEM_BLOCK_SIZE; |
| avs3_dec->sys_imem_ptr_v += 2*FB_IFBUF_SYS_IMEM_BLOCK_SIZE; |
| #else |
| if (avs3_dec->ins_offset > 256) { |
| avs3_print(dec, 0, |
| "!!!!!Error!!!!!!!!, ins_offset %d is too big (>256)\n", avs3_dec->ins_offset); |
| avs3_dec->ins_offset = 256; |
| } |
| memcpy(avs3_dec->sys_imem_ptr_v, (void*)(&avs3_dec->instruction[0]), avs3_dec->ins_offset*4); |
| //copyToDDR_32bits(dec->fr.sys_imem_ptr, instruction, ins_offset*4, 0); |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, |
| "cur_imem_ptr_v 0x%x: %02x %02x %02x %02x\n", |
| avs3_dec->sys_imem_ptr_v, |
| ((u8 *)avs3_dec->sys_imem_ptr_v)[0], ((u8 *)avs3_dec->sys_imem_ptr_v)[1], |
| ((u8 *)avs3_dec->sys_imem_ptr_v)[2], ((u8 *)avs3_dec->sys_imem_ptr_v)[3]); |
| avs3_dec->sys_imem_ptr += FB_IFBUF_SYS_IMEM_BLOCK_SIZE; |
| avs3_dec->sys_imem_ptr_v += FB_IFBUF_SYS_IMEM_BLOCK_SIZE; |
| #endif |
| if (avs3_dec->sys_imem_ptr >= avs3_dec->fb_buf_sys_imem.buf_end) { |
| avs3_print(dec, AVS3_DBG_BUFMGR, |
| "sys_imem_ptr is 0x%x, wrap around\n", avs3_dec->sys_imem_ptr); |
| avs3_dec->sys_imem_ptr = avs3_dec->fb_buf_sys_imem.buf_start; |
| avs3_dec->sys_imem_ptr_v = avs3_dec->fb_buf_sys_imem_addr; |
| } |
| if (dec->front_back_mode == 1) { |
| //WRITE_VREG(HEVC_ASSIST_RING_F_INDEX, 8); |
| //WRITE_VREG(HEVC_ASSIST_RING_F_WPTR, sys_imem_ptr); |
| //imem_count++; |
| WRITE_VREG(DOS_HEVC_STALL_START, 0); // disable stall |
| } |
| } |
| |
| if ((start_code == I_PICTURE_START_CODE) |
| || (start_code == PB_PICTURE_START_CODE) |
| || (start_code == SEQUENCE_END_CODE) |
| || (start_code == VIDEO_EDIT_CODE)) { |
| avs3_prepare_display_buf(dec); |
| } |
| } |
| mutex_unlock(&dec->slice_header_lock); |
| irq_handled_exit: |
| |
| dec->process_busy = 0; |
| return IRQ_HANDLED; |
| } |
| |
| static irqreturn_t vavs3_isr(int irq, void *data) |
| { |
| //int i; |
| unsigned int dec_status; |
| struct AVS3Decoder_s *dec = (struct AVS3Decoder_s *)data; |
| uint debug_tag = 0; |
| #if 0 |
| if ((debug & AVS3_DBG_BE_SIMULATE_IRQ) |
| &&(READ_VREG(DEBUG_REG1_DBE) || |
| READ_VREG(HEVC_DEC_STATUS_DBE)== HEVC_BE_DECODE_DATA_DONE)) { |
| pr_info("Simulate BE irq\n"); |
| WRITE_VREG(dec->backend_ASSIST_MBOX0_IRQ_REG, 1); |
| } |
| #endif |
| |
| dec_status = READ_VREG(HEVC_DEC_STATUS_REG); |
| if (dec_status == HEVC_DECPIC_DATA_DONE) { |
| vdec_profile(hw_to_vdec(dec), VDEC_PROFILE_DECODER_END, CORE_MASK_HEVC); |
| } |
| |
| WRITE_VREG(dec->ASSIST_MBOX0_CLR_REG, 1); |
| |
| if ((dec_status == AVS3_HEAD_PIC_I_READY) || |
| (dec_status == AVS3_HEAD_PIC_PB_READY)) { |
| decoder_trace(dec->trace.decode_time_name, DECODER_ISR_HEAD_DONE, TRACE_PERFORMANCE_DETAIL); |
| } else if (dec_status == HEVC_DECPIC_DATA_DONE) { |
| decoder_trace(dec->trace.decode_time_name, DECODER_ISR_PIC_DONE, TRACE_PERFORMANCE_DETAIL); |
| } |
| |
| |
| if (!dec) |
| return IRQ_HANDLED; |
| if (dec->init_flag == 0) |
| return IRQ_HANDLED; |
| if (dec->process_busy)/*on process.*/ |
| return IRQ_HANDLED; |
| dec->dec_status = dec_status; |
| dec->process_busy = 1; |
| #if 0 |
| if (debug & AVS3_DBG_IRQ_EVENT) { |
| if (dec->front_back_mode != 1) |
| avs3_print(dec, 0, |
| "avs3 isr dec status = 0x%x, debug_tag 0x%x, lcu 0x%x shiftbyte 0x%x (%x %x lev %x, wr %x, rd %x) HEVC_SAO_CRC %x\n", |
| dec_status, READ_HREG(DEBUG_REG1), READ_VREG(HEVC_PARSER_LCU_START), |
| READ_VREG(HEVC_SHIFT_BYTE_COUNT), |
| READ_VREG(HEVC_STREAM_START_ADDR), |
| READ_VREG(HEVC_STREAM_END_ADDR), |
| READ_VREG(HEVC_STREAM_LEVEL), |
| READ_VREG(HEVC_STREAM_WR_PTR), |
| READ_VREG(HEVC_STREAM_RD_PTR), |
| (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_S5) ? |
| READ_VREG(HEVC_SAO_CRC) : 0 |
| ); |
| else |
| avs3_print(dec, 0, |
| "avs3 isr dec status = 0x%x, debug_tag 0x%x, lcu 0x%x shiftbyte 0x%x (%x %x lev %x, wr %x, rd %x) [BE] pc %x psr %x DEC_STATUS %x\n", |
| dec_status, READ_HREG(DEBUG_REG1), READ_VREG(HEVC_PARSER_LCU_START), |
| READ_VREG(HEVC_SHIFT_BYTE_COUNT), |
| READ_VREG(HEVC_STREAM_START_ADDR), |
| READ_VREG(HEVC_STREAM_END_ADDR), |
| READ_VREG(HEVC_STREAM_LEVEL), |
| READ_VREG(HEVC_STREAM_WR_PTR), |
| READ_VREG(HEVC_STREAM_RD_PTR), |
| READ_VREG(HEVC_MPC_E_DBE), |
| READ_VREG(HEVC_MPSR_DBE), |
| READ_VREG(HEVC_DEC_STATUS_DBE) |
| ); |
| } |
| #endif |
| |
| if (udebug_flag) |
| debug_tag = READ_HREG(DEBUG_REG1); |
| if (debug_tag != 0) { |
| #if 0 |
| handle_ucode_dbg(dec, debug_tag); |
| dec->process_busy = 0; |
| return IRQ_HANDLED; |
| #else |
| decoder_trace(dec->trace.decode_time_name, DECODER_ISR_END, TRACE_BASIC); |
| return IRQ_WAKE_THREAD; |
| #endif |
| } |
| |
| if (!dec->m_ins_flag) { |
| if (dec->error_flag == 1) { |
| dec->error_flag = 2; |
| dec->process_busy = 0; |
| return IRQ_HANDLED; |
| } else if (dec->error_flag == 3) { |
| dec->process_busy = 0; |
| return IRQ_HANDLED; |
| } |
| |
| if ((dec->pic_list_init_flag) && |
| get_free_buf_count(dec) <= 0) { |
| /* |
| if (dec->wait_buf == 0) |
| pr_info("set wait_buf to 1\r\n"); |
| */ |
| dec->wait_buf = 1; |
| dec->process_busy = 0; |
| if (debug & AVS3_DBG_IRQ_EVENT) |
| avs3_print(dec, 0, "wait_buf\n"); |
| return IRQ_HANDLED; |
| } else if (force_disp_pic_index) { |
| dec->process_busy = 0; |
| return IRQ_HANDLED; |
| } |
| } |
| decoder_trace(dec->trace.decode_time_name, DECODER_ISR_END, TRACE_BASIC); |
| return IRQ_WAKE_THREAD; |
| } |
| |
| #ifdef NEW_FB_CODE |
| static void avs3_check_timer_back_func(struct timer_list *timer) |
| { |
| struct AVS3Decoder_s *dec = container_of(timer, |
| struct AVS3Decoder_s, timer_back); |
| |
| if (dec->init_flag == 0) { |
| if (dec->stat & STAT_TIMER_BACK_ARM) { |
| mod_timer(&dec->timer_back, jiffies + PUT_INTERVAL); |
| } |
| return; |
| } |
| |
| if ( |
| (decode_timeout_val_back > 0) && |
| (dec->start_process_time_back > 0) && |
| ((1000 * (jiffies - dec->start_process_time_back) / HZ) |
| > decode_timeout_val_back) |
| ) { |
| if (dec->decode_timeout_count_back > 0) |
| dec->decode_timeout_count_back--; |
| if (dec->decode_timeout_count_back == 0) |
| timeout_process_back(dec); |
| } |
| |
| #if 0 |
| if (debug & AVS3_DBG_BE_SIMULATE_IRQ) { |
| //struct vdec_s *vdec = hw_to_vdec(dec); |
| pr_info("Simulate BE irq\n"); |
| WRITE_VREG(dec->backend_ASSIST_MBOX0_IRQ_REG, 1); |
| //if (avs3_back_irq_cb(vdec, 0) == IRQ_WAKE_THREAD) |
| // avs3_back_threaded_irq_cb(vdec, 0); |
| } |
| #endif |
| mod_timer(timer, jiffies + PUT_INTERVAL); |
| |
| } |
| #endif |
| |
| static void vavs3_put_timer_func(struct timer_list *timer) |
| { |
| struct AVS3Decoder_s *dec = container_of(timer, |
| struct AVS3Decoder_s, timer); |
| //uint8_t empty_flag; |
| //unsigned int buf_level; |
| |
| //enum receiver_start_e state = RECEIVER_INACTIVE; |
| if (dec->init_flag == 0) { |
| if (dec->stat & STAT_TIMER_ARM) { |
| timer->expires = jiffies + PUT_INTERVAL; |
| add_timer(&dec->timer); |
| } |
| return; |
| } |
| if (dec->m_ins_flag == 0) { |
| #ifndef PXP_DEBUG |
| if (vf_get_receiver(dec->provider_name)) { |
| state = |
| vf_notify_receiver(dec->provider_name, |
| VFRAME_EVENT_PROVIDER_QUREY_STATE, |
| NULL); |
| if ((state == RECEIVER_STATE_NULL) |
| || (state == RECEIVER_STATE_NONE)) |
| state = RECEIVER_INACTIVE; |
| } else |
| state = RECEIVER_INACTIVE; |
| |
| empty_flag = (READ_VREG(HEVC_PARSER_INT_STATUS) >> 6) & 0x1; |
| /* error watchdog */ |
| if (empty_flag == 0) { |
| /* decoder has input */ |
| if ((debug & AVS3_DBG_DIS_LOC_ERROR_PROC) == 0) { |
| |
| buf_level = READ_VREG(HEVC_STREAM_LEVEL); |
| /* receiver has no buffer to recycle */ |
| if ((state == RECEIVER_INACTIVE) && |
| (kfifo_is_empty(&dec->display_q) && |
| buf_level > 0x200) |
| ) { |
| WRITE_VREG |
| (dec->ASSIST_MBOX0_IRQ_REG, |
| 0x1); |
| } |
| } |
| |
| if ((debug & AVS3_DBG_DIS_SYS_ERROR_PROC) == 0) { |
| /* receiver has no buffer to recycle */ |
| /*if ((state == RECEIVER_INACTIVE) && |
| (kfifo_is_empty(&dec->display_q))) { |
| pr_info("avs3 something error,need reset\n"); |
| }*/ |
| } |
| } |
| #endif |
| } else { |
| if ( |
| (decode_timeout_val > 0) && |
| (dec->start_process_time > 0) && |
| ((1000 * (jiffies - dec->start_process_time) / HZ) |
| > decode_timeout_val) |
| ) { |
| int current_lcu_idx = |
| READ_VREG(HEVC_PARSER_LCU_START) |
| & 0xffffff; |
| if (dec->last_lcu_idx == current_lcu_idx) { |
| if (dec->decode_timeout_count > 0) |
| dec->decode_timeout_count--; |
| if (dec->decode_timeout_count == 0) { |
| if (input_frame_based( |
| hw_to_vdec(dec)) || |
| (READ_VREG(HEVC_STREAM_LEVEL) > 0x200)) |
| timeout_process(dec); |
| else { |
| avs3_print(dec, 0, |
| "timeout & empty, again\n"); |
| dec_again_process(dec); |
| } |
| } |
| } else { |
| start_process_time(dec); |
| dec->last_lcu_idx = current_lcu_idx; |
| } |
| } |
| } |
| if ((dec->ucode_pause_pos != 0) && |
| (dec->ucode_pause_pos != 0xffffffff) && |
| udebug_pause_pos != dec->ucode_pause_pos) { |
| dec->ucode_pause_pos = 0; |
| WRITE_VREG(DEBUG_REG1, 0); |
| } |
| if (debug & AVS3_DBG_DUMP_DATA) { |
| debug &= ~AVS3_DBG_DUMP_DATA; |
| avs3_print(dec, 0, |
| "%s: chunk size 0x%x off 0x%x sum 0x%x\n", |
| __func__, |
| dec->chunk->size, |
| dec->chunk->offset, |
| get_data_check_sum(dec, dec->chunk->size) |
| ); |
| dump_data(dec, dec->chunk->size); |
| } |
| if (debug & AVS3_DBG_DUMP_PIC_LIST) { |
| print_pic_pool(&dec->avs3_dec, ""); |
| debug &= ~AVS3_DBG_DUMP_PIC_LIST; |
| } |
| if (debug & AVS3_DBG_TRIG_SLICE_SEGMENT_PROC) { |
| WRITE_VREG(dec->ASSIST_MBOX0_IRQ_REG, 0x1); |
| debug &= ~AVS3_DBG_TRIG_SLICE_SEGMENT_PROC; |
| } |
| if (debug & AVS3_DBG_DUMP_RPM_BUF) { |
| int i; |
| |
| pr_info("RPM:\n"); |
| for (i = 0; i < RPM_BUF_SIZE; i += 4) { |
| int ii; |
| if ((i & 0xf) == 0) |
| pr_info("%03x: ", i); |
| for (ii = 0; ii < 4; ii++) { |
| pr_info("%04x ", |
| dec->lmem_ptr[i + 3 - ii]); |
| } |
| if (((i + ii) & 0xf) == 0) |
| pr_info("\n"); |
| } |
| debug &= ~AVS3_DBG_DUMP_RPM_BUF; |
| } |
| if (debug & AVS3_DBG_DUMP_LMEM_BUF) { |
| int i; |
| |
| pr_info("LMEM:\n"); |
| for (i = 0; i < LMEM_BUF_SIZE; i += 4) { |
| int ii; |
| if ((i & 0xf) == 0) |
| pr_info("%03x: ", i); |
| for (ii = 0; ii < 4; ii++) { |
| pr_info("%04x ", |
| dec->lmem_ptr[i + 3 - ii]); |
| } |
| if (((i + ii) & 0xf) == 0) |
| pr_info("\n"); |
| } |
| debug &= ~AVS3_DBG_DUMP_LMEM_BUF; |
| } |
| /*if (debug & AVS3_DBG_HW_RESET) { |
| }*/ |
| |
| if (radr != 0) { |
| if (rval != 0) { |
| WRITE_VREG(radr, rval); |
| pr_info("WRITE_VREG(%x,%x)\n", radr, rval); |
| } else |
| pr_info("READ_VREG(%x)=%x\n", radr, READ_VREG(radr)); |
| rval = 0; |
| radr = 0; |
| } |
| if (pop_shorts != 0) { |
| int i; |
| u32 sum = 0; |
| pr_info("pop stream 0x%x shorts\r\n", pop_shorts); |
| for (i = 0; i < pop_shorts; i++) { |
| u32 data = |
| (READ_HREG(HEVC_SHIFTED_DATA) >> 16); |
| WRITE_VREG(HEVC_SHIFT_COMMAND, |
| (1<<7)|16); |
| if ((i & 0xf) == 0) |
| pr_info("%04x:", i); |
| pr_info("%04x ", data); |
| if (((i + 1) & 0xf) == 0) |
| pr_info("\r\n"); |
| sum += data; |
| } |
| pr_info("\r\nsum = %x\r\n", sum); |
| pop_shorts = 0; |
| } |
| if (dbg_cmd != 0) { |
| if (dbg_cmd == 1) { |
| u32 disp_laddr; |
| if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXBB && |
| get_double_write_mode(dec) == 0) { |
| disp_laddr = |
| READ_VCBUS_REG(AFBC_BODY_BADDR) << 4; |
| } else { |
| struct canvas_s cur_canvas; |
| canvas_read((READ_VCBUS_REG(VD1_IF0_CANVAS0) |
| & 0xff), &cur_canvas); |
| disp_laddr = cur_canvas.addr; |
| } |
| pr_info("current displayed buffer address %x\r\n", |
| disp_laddr); |
| } |
| #ifdef DEBUG_CMD |
| else if ((dbg_cmd & 0xf) == 2) { |
| d_dump(dec, dbg_cmd & (~0xf), 128, NULL, NULL); |
| } |
| #endif |
| dbg_cmd = 0; |
| } |
| /*don't changed at start.*/ |
| if (dec->get_frame_dur && dec->show_frame_num > 60 && |
| dec->frame_dur > 0 && dec->saved_resolution != |
| frame_width * frame_height * |
| (96000 / dec->frame_dur)) { |
| int fps = 96000 / dec->frame_dur; |
| if (hevc_source_changed(VFORMAT_AVS3, |
| frame_width, frame_height, fps) > 0) |
| dec->saved_resolution = frame_width * |
| frame_height * fps; |
| } |
| |
| timer->expires = jiffies + PUT_INTERVAL; |
| add_timer(timer); |
| } |
| |
| int vavs3_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) |
| { |
| struct AVS3Decoder_s *dec = |
| (struct AVS3Decoder_s *)vdec->private; |
| |
| if (!dec) |
| return -1; |
| |
| vstatus->frame_width = dec->frame_width; |
| vstatus->frame_height = dec->frame_height; |
| |
| if (dec->frame_dur != 0) |
| vstatus->frame_rate = ((96000 * 10 / dec->frame_dur) % 10) < 5 ? |
| 96000 / dec->frame_dur : (96000 / dec->frame_dur +1); |
| else |
| vstatus->frame_rate = -1; |
| vstatus->error_count = 0; |
| vstatus->status = dec->stat | dec->fatal_error; |
| vstatus->frame_dur = dec->frame_dur; |
| vstatus->bit_rate = dec->gvs->bit_rate; |
| vstatus->frame_data = dec->gvs->frame_data; |
| vstatus->total_data = dec->gvs->total_data; |
| vstatus->frame_count = dec->gvs->frame_count; |
| vstatus->error_frame_count = dec->gvs->error_frame_count; |
| vstatus->drop_frame_count = dec->gvs->drop_frame_count; |
| vstatus->i_decoded_frames = dec->gvs->i_decoded_frames; |
| vstatus->i_lost_frames = dec->gvs->i_lost_frames; |
| vstatus->i_concealed_frames = dec->gvs->i_concealed_frames; |
| vstatus->p_decoded_frames = dec->gvs->p_decoded_frames; |
| vstatus->p_lost_frames = dec->gvs->p_lost_frames; |
| vstatus->p_concealed_frames = dec->gvs->p_concealed_frames; |
| vstatus->b_decoded_frames = dec->gvs->b_decoded_frames; |
| vstatus->b_lost_frames = dec->gvs->b_lost_frames; |
| vstatus->b_concealed_frames = dec->gvs->b_concealed_frames; |
| vstatus->total_data = dec->gvs->total_data; |
| vstatus->samp_cnt = dec->gvs->samp_cnt; |
| vstatus->offset = dec->gvs->offset; |
| snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name), |
| "%s", DRIVER_NAME); |
| return 0; |
| } |
| |
| int vavs3_set_isreset(struct vdec_s *vdec, int isreset) |
| { |
| #ifndef PXP_DEBUG |
| is_reset = isreset; |
| #endif |
| return 0; |
| } |
| |
| static void vavs3_prot_init(struct AVS3Decoder_s *dec) |
| { |
| unsigned int data32; |
| |
| avs3_config_work_space_hw(dec); |
| if (dec->pic_list_init_flag) |
| init_pic_list_hw(dec); |
| #ifdef TMP_DEBUG |
| avs2_init_decoder_hw(dec); |
| #else |
| avs3_init_decoder_hw(dec); |
| #endif |
| #if 1 |
| avs3_print(dec, AVS3_DBG_BUFMGR_MORE, |
| "%s\n", __func__); |
| #if 0 |
| data32 = READ_VREG(HEVC_STREAM_CONTROL); |
| data32 = data32 | |
| (1 << 0)/*stream_fetch_enable*/ |
| ; |
| WRITE_VREG(HEVC_STREAM_CONTROL, data32); |
| #endif |
| #if 0 |
| data32 = READ_VREG(HEVC_SHIFT_STARTCODE); |
| if (data32 != 0x00000100) { |
| pr_info("avs3 prot init error %d\n", __LINE__); |
| return; |
| } |
| data32 = READ_VREG(HEVC_SHIFT_EMULATECODE); |
| if (data32 != 0x00000300) { |
| pr_info("avs3 prot init error %d\n", __LINE__); |
| return; |
| } |
| WRITE_VREG(HEVC_SHIFT_STARTCODE, 0x12345678); |
| WRITE_VREG(HEVC_SHIFT_EMULATECODE, 0x9abcdef0); |
| data32 = READ_VREG(HEVC_SHIFT_STARTCODE); |
| if (data32 != 0x12345678) { |
| pr_info("avs3 prot init error %d\n", __LINE__); |
| return; |
| } |
| data32 = READ_VREG(HEVC_SHIFT_EMULATECODE); |
| if (data32 != 0x9abcdef0) { |
| pr_info("avs3 prot init error %d\n", __LINE__); |
| return; |
| } |
| #endif |
| WRITE_VREG(HEVC_SHIFT_STARTCODE, 0x00000100); |
| WRITE_VREG(HEVC_SHIFT_EMULATECODE, 0x00000000); |
| |
| // Set MCR fetch priorities |
| data32 = 0x1 | (0x1 << 2) | (0x1 <<3) | (24 << 4) | (32 << 11) | (24 << 18) | (32 << 25); |
| WRITE_VREG(HEVCD_MPP_DECOMP_AXIURG_CTL, data32); |
| |
| #endif |
| |
| WRITE_VREG(HEVC_WAIT_FLAG, 1); |
| |
| /* WRITE_VREG(HEVC_MPSR, 1); */ |
| |
| /* clear mailbox interrupt */ |
| WRITE_VREG(dec->ASSIST_MBOX0_CLR_REG, 1); |
| |
| /* enable mailbox interrupt */ |
| WRITE_VREG(dec->ASSIST_MBOX0_MASK, 1); |
| /* disable PSCALE for hardware sharing */ |
| #ifndef FOR_S5 |
| WRITE_VREG(HEVC_PSCALE_CTRL, 0); |
| #endif |
| |
| WRITE_VREG(DEBUG_REG1, 0x0); |
| /*check vps/sps/pps/i-slice in ucode*/ |
| WRITE_VREG(NAL_SEARCH_CTL, 0x8); |
| |
| WRITE_VREG(DECODE_STOP_POS, udebug_flag); |
| #if (defined DEBUG_UCODE_LOG) || (defined DEBUG_CMD) |
| WRITE_VREG(HEVC_DBG_LOG_ADR, dec->ucode_log_phy_addr); |
| #endif |
| config_cuva_buf(dec); |
| if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_S5) { |
| WRITE_VREG(HEVC_SAO_CRC, 0); |
| if (dec->front_back_mode == 1) |
| WRITE_VREG(HEVC_SAO_CRC_DBE1, 0); |
| } |
| |
| } |
| |
| #ifdef I_ONLY_SUPPORT |
| static int vavs3_set_trickmode(struct vdec_s *vdec, unsigned long trickmode) |
| { |
| struct AVS3Decoder_s *dec = |
| (struct AVS3Decoder_s *)vdec->private; |
| if (i_only_flag & 0x100) |
| return 0; |
| if (trickmode == TRICKMODE_I || trickmode == TRICKMODE_I_HEVC) |
| dec->i_only = 0x3; |
| else if (trickmode == TRICKMODE_NONE) |
| dec->i_only = 0x0; |
| return 0; |
| } |
| #endif |
| |
| static int vavs3_local_init(struct AVS3Decoder_s *dec) |
| { |
| int i; |
| int ret; |
| int width, height; |
| |
| dec->vavs3_ratio = dec->vavs3_amstream_dec_info.ratio; |
| |
| dec->gvs = vzalloc(sizeof(struct vdec_info)); |
| if (NULL == dec->gvs) { |
| avs3_print(dec, 0, |
| "the struct of vdec status malloc failed.\n"); |
| return -1; |
| } |
| #ifdef DEBUG_PTS |
| dec->pts_missed = 0; |
| dec->pts_hit = 0; |
| #endif |
| dec->new_frame_displayed = 0; |
| dec->last_put_idx = -1; |
| dec->saved_resolution = 0; |
| dec->get_frame_dur = false; |
| on_no_keyframe_skiped = 0; |
| width = dec->vavs3_amstream_dec_info.width; |
| height = dec->vavs3_amstream_dec_info.height; |
| dec->frame_dur = |
| (dec->vavs3_amstream_dec_info.rate == |
| 0) ? 3600 : dec->vavs3_amstream_dec_info.rate; |
| if (width && height) |
| dec->frame_ar = height * 0x100 / width; |
| /* |
| TODO:FOR VERSION |
| */ |
| avs3_print(dec, AVS3_DBG_BUFMGR, |
| "avs3: ver (%d,%d) decinfo: %dx%d rate=%d\n", avs3_version, |
| 0, width, height, dec->frame_dur); |
| |
| if (dec->frame_dur == 0) |
| dec->frame_dur = 96000 / 24; |
| #ifdef I_ONLY_SUPPORT |
| if (i_only_flag & 0x100) |
| dec->i_only = i_only_flag & 0xff; |
| else if ((unsigned long) dec->vavs3_amstream_dec_info.param |
| & 0x08) |
| dec->i_only = 0x7; |
| else |
| dec->i_only = 0x0; |
| #endif |
| INIT_KFIFO(dec->display_q); |
| INIT_KFIFO(dec->newframe_q); |
| |
| for (i = 0; i < VF_POOL_SIZE; i++) { |
| const struct vframe_s *vf = &dec->vfpool[i]; |
| dec->vfpool[i].index = -1; |
| kfifo_put(&dec->newframe_q, vf); |
| } |
| |
| ret = avs3_local_init(dec); |
| |
| return ret; |
| } |
| |
| static s32 vavs3_init(struct vdec_s *vdec) |
| { |
| int ret = -1, size = -1; |
| int fw_size = 0x1000 * 16; |
| struct firmware_s *fw = NULL; |
| struct AVS3Decoder_s *dec = (struct AVS3Decoder_s *)vdec->private; |
| struct avs3_decoder *avs3_dec = &dec->avs3_dec; |
| #ifdef NEW_FB_CODE |
| struct firmware_s *fw_back = NULL; |
| #endif |
| |
| avs3_dec->start_time = div64_u64(local_clock(), 1000); |
| timer_setup(&dec->timer, vavs3_put_timer_func, 0); |
| #ifdef NEW_FB_CODE |
| timer_setup(&dec->timer_back, avs3_check_timer_back_func, 0); |
| dec->stat |= STAT_TIMER_BACK_INIT; |
| #endif |
| |
| dec->stat |= STAT_TIMER_INIT; |
| if (vavs3_local_init(dec) < 0) |
| return -EBUSY; |
| |
| vdec_set_vframe_comm(vdec, DRIVER_NAME); |
| |
| fw = vmalloc(sizeof(struct firmware_s) + fw_size); |
| if (IS_ERR_OR_NULL(fw)) |
| return -ENOMEM; |
| #ifdef NEW_FB_CODE |
| if (dec->front_back_mode == 1 || dec->front_back_mode == 3) { |
| fw_back = vzalloc(sizeof(struct firmware_s) + fw_size); |
| if (IS_ERR_OR_NULL(fw_back)) |
| return -ENOMEM; |
| |
| size = get_firmware_data(VIDEO_DEC_AVS3_FRONT, fw->data); |
| |
| fw_back->len = get_firmware_data(VIDEO_DEC_AVS3_BACK, fw_back->data); |
| if (fw_back->len < 0) { |
| pr_err("get back firmware fail.\n"); |
| vfree(fw_back); |
| return -1; |
| } |
| } else |
| #endif |
| size = get_firmware_data(VIDEO_DEC_AVS3, fw->data); |
| if (size < 0) { |
| pr_err("get firmware fail.\n"); |
| vfree(fw); |
| return -1; |
| } |
| |
| fw->len = fw_size; |
| |
| if (dec->m_ins_flag) { |
| dec->timer.expires = jiffies + PUT_INTERVAL; |
| #ifdef NEW_FB_CODE |
| if (dec->front_back_mode) { |
| dec->timer_back.expires = jiffies + PUT_INTERVAL; |
| dec->fw_back = fw_back; |
| } |
| #endif |
| /*add_timer(&dec->timer); |
| |
| dec->stat |= STAT_TIMER_ARM; |
| dec->stat |= STAT_ISR_REG;*/ |
| |
| INIT_WORK(&dec->work, avs3_work); |
| #ifdef NEW_FB_CODE |
| if (dec->front_back_mode) { |
| INIT_WORK(&dec->work_back, avs3_work_back); |
| INIT_WORK(&dec->timeout_work_back, avs3_timeout_work_back); |
| mutex_init(&dec->fb_mutex); |
| } |
| #endif |
| dec->fw = fw; |
| |
| return 0; |
| } |
| |
| amhevc_enable(); |
| |
| ret = amhevc_loadmc_ex(VFORMAT_AVS3, NULL, fw->data); |
| if (ret < 0) { |
| amhevc_disable(); |
| vfree(fw); |
| pr_err("AVS3: the %s fw loading failed, err: %x\n", |
| tee_enabled() ? "TEE" : "local", ret); |
| return -EBUSY; |
| } |
| |
| vfree(fw); |
| |
| dec->stat |= STAT_MC_LOAD; |
| |
| /* enable AMRISC side protocol */ |
| vavs3_prot_init(dec); |
| |
| if (vdec_request_threaded_irq(VDEC_IRQ_0, |
| vavs3_isr, |
| vavs3_isr_thread_fn, |
| IRQF_ONESHOT,/*run thread on this irq disabled*/ |
| "vavs3-irq", (void *)dec)) { |
| pr_info("vavs3 irq register error.\n"); |
| amhevc_disable(); |
| return -ENOENT; |
| } |
| dec->stat |= STAT_ISR_REG; |
| |
| dec->provider_name = PROVIDER_NAME; |
| vf_provider_init(&vavs3_vf_prov, PROVIDER_NAME, |
| &vavs3_vf_provider, dec); |
| vf_reg_provider(&vavs3_vf_prov); |
| vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_START, NULL); |
| if (dec->frame_dur != 0) { |
| if (!is_reset) |
| vf_notify_receiver(dec->provider_name, |
| VFRAME_EVENT_PROVIDER_FR_HINT, |
| (void *) |
| ((unsigned long)dec->frame_dur)); |
| } |
| dec->stat |= STAT_VF_HOOK; |
| |
| dec->timer.expires = jiffies + PUT_INTERVAL; |
| add_timer(&dec->timer); |
| dec->stat |= STAT_TIMER_ARM; |
| |
| /* dec->stat |= STAT_KTHREAD; */ |
| dec->process_busy = 0; |
| avs3_print(dec, AVS3_DBG_BUFMGR_MORE, |
| "%d, vavs3_init, RP=0x%x\n", |
| __LINE__, READ_VREG(HEVC_STREAM_RD_PTR)); |
| return 0; |
| } |
| |
| static int vmavs3_stop(struct AVS3Decoder_s *dec) |
| { |
| dec->init_flag = 0; |
| dec->first_sc_checked = 0; |
| if (dec->stat & STAT_TIMER_ARM) { |
| del_timer_sync(&dec->timer); |
| dec->stat &= ~STAT_TIMER_ARM; |
| } |
| #ifdef NEW_FB_CODE |
| if (dec->front_back_mode && (dec->stat & STAT_TIMER_BACK_ARM)) { |
| del_timer_sync(&dec->timer_back); |
| dec->stat &= ~STAT_TIMER_BACK_ARM; |
| } |
| #endif |
| if (dec->stat & STAT_VF_HOOK) { |
| if (!is_reset) |
| vf_notify_receiver(dec->provider_name, |
| VFRAME_EVENT_PROVIDER_FR_END_HINT, |
| NULL); |
| |
| vf_unreg_provider(&vavs3_vf_prov); |
| dec->stat &= ~STAT_VF_HOOK; |
| } |
| avs3_local_uninit(dec); |
| reset_process_time(dec); |
| cancel_work_sync(&dec->work); |
| #ifdef NEW_FB_CODE |
| if (dec->front_back_mode) { |
| cancel_work_sync(&dec->work_back); |
| vfree(dec->fw_back); |
| dec->fw_back = NULL; |
| } |
| #endif |
| uninit_mmu_buffers(dec); |
| if (dec->fw) { |
| vfree(dec->fw); |
| dec->fw = NULL; |
| } |
| |
| return 0; |
| } |
| |
| static int vavs3_stop(struct AVS3Decoder_s *dec) |
| { |
| |
| dec->init_flag = 0; |
| dec->first_sc_checked = 0; |
| if (dec->stat & STAT_VDEC_RUN) { |
| amhevc_stop(); |
| dec->stat &= ~STAT_VDEC_RUN; |
| } |
| |
| if (dec->stat & STAT_ISR_REG) { |
| if (!dec->m_ins_flag) |
| WRITE_VREG(dec->ASSIST_MBOX0_MASK, 0); |
| vdec_free_irq(VDEC_IRQ_0, (void *)dec); |
| dec->stat &= ~STAT_ISR_REG; |
| } |
| |
| if (dec->stat & STAT_TIMER_ARM) { |
| del_timer_sync(&dec->timer); |
| dec->stat &= ~STAT_TIMER_ARM; |
| } |
| #ifdef NEW_FB_CODE |
| if (dec->front_back_mode && (dec->stat & STAT_TIMER_BACK_ARM)) { |
| del_timer_sync(&dec->timer_back); |
| dec->stat &= ~STAT_TIMER_BACK_ARM; |
| } |
| #endif |
| |
| if (dec->stat & STAT_VF_HOOK) { |
| if (!is_reset) |
| vf_notify_receiver(dec->provider_name, |
| VFRAME_EVENT_PROVIDER_FR_END_HINT, |
| NULL); |
| |
| vf_unreg_provider(&vavs3_vf_prov); |
| dec->stat &= ~STAT_VF_HOOK; |
| } |
| avs3_local_uninit(dec); |
| |
| if (dec->m_ins_flag) { |
| cancel_work_sync(&dec->work); |
| #ifdef NEW_FB_CODE |
| if (dec->front_back_mode) { |
| cancel_work_sync(&dec->work_back); |
| vfree(dec->fw_back); |
| dec->fw_back = NULL; |
| } |
| #endif |
| } else |
| amhevc_disable(); |
| uninit_mmu_buffers(dec); |
| |
| return 0; |
| } |
| |
| static int amvdec_avs3_mmu_init(struct AVS3Decoder_s *dec) |
| { |
| int tvp_flag = vdec_secure(hw_to_vdec(dec)) ? |
| CODEC_MM_FLAGS_TVP : 0; |
| int buf_size = 48; |
| |
| dec->need_cache_size = buf_size * SZ_1M; |
| dec->sc_start_time = get_jiffies_64(); |
| #ifdef AVS3_10B_MMU |
| if (dec->mmu_enable) { |
| dec->mmu_box = decoder_mmu_box_alloc_box(DRIVER_NAME, |
| dec->index, FRAME_BUFFERS, |
| dec->need_cache_size, |
| tvp_flag |
| ); |
| if (!dec->mmu_box) { |
| pr_err("avs3 alloc mmu box failed!!\n"); |
| return -1; |
| } |
| #ifdef NEW_FB_CODE |
| if (dec->front_back_mode) { |
| dec->mmu_box_1 = decoder_mmu_box_alloc_box(DRIVER_NAME, |
| dec->index, FRAME_BUFFERS, |
| dec->need_cache_size, |
| tvp_flag |
| ); |
| if (!dec->mmu_box_1) { |
| pr_err("avs3 alloc mmu box1 failed!!\n"); |
| return -1; |
| } |
| } |
| } |
| #endif |
| #ifdef AVS3_10B_MMU_DW |
| if (dec->dw_mmu_enable) { |
| dec->dw_mmu_box = decoder_mmu_box_alloc_box(DRIVER_NAME, |
| dec->index, FRAME_BUFFERS, |
| dec->need_cache_size, |
| tvp_flag |
| ); |
| if (!dec->dw_mmu_box) { |
| pr_err("avs3 alloc dw mmu box failed!!\n"); |
| dec->dw_mmu_enable = 0; |
| } |
| #ifdef NEW_FB_CODE |
| if (dec->front_back_mode) { |
| dec->dw_mmu_box_1 = decoder_mmu_box_alloc_box(DRIVER_NAME, |
| dec->index, FRAME_BUFFERS, |
| dec->need_cache_size, |
| tvp_flag |
| ); |
| if (!dec->dw_mmu_box_1) { |
| pr_err("avs3 alloc dw mmu box1 failed!!\n"); |
| dec->dw_mmu_enable = 0; |
| } |
| } |
| #endif |
| } |
| #endif |
| dec->bmmu_box = decoder_bmmu_box_alloc_box( |
| DRIVER_NAME, |
| dec->index, |
| MAX_BMMU_BUFFER_NUM, |
| 4 + PAGE_SHIFT, |
| CODEC_MM_FLAGS_CMA_CLEAR | |
| CODEC_MM_FLAGS_FOR_VDECODER | |
| tvp_flag, |
| BMMU_ALLOC_FLAGS_WAITCLEAR); |
| if (!dec->bmmu_box) { |
| pr_err("avs3 alloc bmmu box failed!!\n"); |
| return -1; |
| } |
| return 0; |
| } |
| |
| static int amvdec_avs3_probe(struct platform_device *pdev) |
| { |
| struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; |
| /*struct BUF_s BUF[MAX_BUF_NUM];*/ |
| struct AVS3Decoder_s *dec = &gAVS3Decoder; |
| int ret; |
| pr_info("%s\n", __func__); |
| |
| dec = vzalloc(sizeof(struct AVS3Decoder_s)); |
| if (!dec) |
| return -ENOMEM; |
| |
| pdata->private = dec; |
| platform_set_drvdata(pdev, pdata); |
| |
| mutex_lock(&vavs3_mutex); |
| |
| dec->init_flag = 0; |
| dec->first_sc_checked = 0; |
| dec->eos = 0; |
| dec->start_process_time = 0; |
| dec->timeout_num = 0; |
| dec->fatal_error = 0; |
| dec->show_frame_num = 0; |
| if (pdata == NULL) { |
| avs3_print(dec, 0, |
| "\namvdec_avs3 memory resource undefined.\n"); |
| mutex_unlock(&vavs3_mutex); |
| return -EFAULT; |
| } |
| dec->m_ins_flag = 0; |
| dec->platform_dev = pdev; |
| platform_set_drvdata(pdev, pdata); |
| |
| #ifdef NEW_FB_CODE |
| dec->front_back_mode = 0; |
| #endif |
| config_hevc_irq_num(dec); |
| |
| #ifdef AVS3_10B_MMU_DW |
| if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_T5D) { |
| dec->dw_mmu_enable = |
| (get_double_write_mode(dec) & 0x20) ? 1 : 0; |
| } else { |
| dec->dw_mmu_enable = 0; |
| } |
| #endif |
| if (amvdec_avs3_mmu_init(dec) < 0) { |
| mutex_unlock(&vavs3_mutex); |
| pr_err("avs3 alloc bmmu box failed!!\n"); |
| return -1; |
| } |
| |
| ret = decoder_bmmu_box_alloc_buf_phy(dec->bmmu_box, WORK_SPACE_BUF_ID, |
| work_buf_size, DRIVER_NAME, &pdata->mem_start); |
| if (ret < 0) { |
| uninit_mmu_buffers(dec); |
| mutex_unlock(&vavs3_mutex); |
| return ret; |
| } |
| dec->buf_size = work_buf_size; |
| |
| dec->buf_start = pdata->mem_start; |
| |
| if (debug) { |
| avs3_print(dec, 0, |
| "===AVS3 decoder mem resource 0x%lx size 0x%x\n", |
| pdata->mem_start, dec->buf_size); |
| } |
| |
| if (pdata->sys_info) { |
| dec->vavs3_amstream_dec_info = *pdata->sys_info; |
| dec->frame_width = dec->vavs3_amstream_dec_info.width; |
| dec->frame_height = dec->vavs3_amstream_dec_info.height; |
| } else { |
| dec->vavs3_amstream_dec_info.width = 0; |
| dec->vavs3_amstream_dec_info.height = 0; |
| dec->vavs3_amstream_dec_info.rate = 30; |
| } |
| dec->cma_dev = pdata->cma_dev; |
| |
| dec->endian = HEVC_CONFIG_LITTLE_ENDIAN; |
| if (is_support_vdec_canvas()) |
| dec->endian = HEVC_CONFIG_BIG_ENDIAN; |
| if (endian) |
| dec->endian = endian; |
| |
| pdata->private = dec; |
| pdata->dec_status = vavs3_dec_status; |
| /*pdata->set_isreset = vavs3_set_isreset;*/ |
| is_reset = 0; |
| if (vavs3_init(pdata) < 0) { |
| pr_info("\namvdec_avs3 init failed.\n"); |
| avs3_local_uninit(dec); |
| uninit_mmu_buffers(dec); |
| pdata->dec_status = NULL; |
| mutex_unlock(&vavs3_mutex); |
| return -ENODEV; |
| } |
| /*set the max clk for smooth playing...*/ |
| hevc_source_changed(VFORMAT_AVS3, |
| 4096, 2048, 60); |
| mutex_unlock(&vavs3_mutex); |
| |
| return 0; |
| } |
| |
| static int amvdec_avs3_remove(struct platform_device *pdev) |
| { |
| struct AVS3Decoder_s *dec = &gAVS3Decoder; |
| if (debug) |
| pr_info("amvdec_avs3_remove\n"); |
| |
| mutex_lock(&vavs3_mutex); |
| |
| vavs3_stop(dec); |
| |
| hevc_source_changed(VFORMAT_AVS3, 0, 0, 0); |
| |
| #ifdef DEBUG_PTS |
| pr_info("pts missed %ld, pts hit %ld, duration %d\n", |
| dec->pts_missed, dec->pts_hit, dec->frame_dur); |
| #endif |
| |
| mutex_unlock(&vavs3_mutex); |
| |
| return 0; |
| } |
| |
| /****************************************/ |
| |
| static struct platform_driver amvdec_avs3_driver = { |
| .probe = amvdec_avs3_probe, |
| .remove = amvdec_avs3_remove, |
| #ifdef CONFIG_PM |
| .suspend = amhevc_suspend, |
| .resume = amhevc_resume, |
| #endif |
| .driver = { |
| .name = DRIVER_NAME, |
| } |
| }; |
| static struct codec_profile_t amvdec_avs3_profile = { |
| .name = "avs3", |
| .profile = "" |
| }; |
| |
| static struct codec_profile_t amvdec_avs3_profile_mult; |
| static unsigned char get_data_check_sum |
| (struct AVS3Decoder_s *dec, int size) |
| { |
| int jj; |
| int sum = 0; |
| u8 *data = NULL; |
| |
| if (!dec->chunk->block->is_mapped) |
| data = codec_mm_vmap(dec->chunk->block->start + |
| dec->chunk->offset, size); |
| else |
| data = ((u8 *)dec->chunk->block->start_virt) + |
| dec->chunk->offset; |
| |
| for (jj = 0; jj < size; jj++) |
| sum += data[jj]; |
| |
| if (!dec->chunk->block->is_mapped) |
| codec_mm_unmap_phyaddr(data); |
| return sum; |
| } |
| |
| static void dump_data(struct AVS3Decoder_s *dec, int size) |
| { |
| int jj; |
| u8 *data = NULL; |
| int padding_size = dec->chunk->offset & |
| (VDEC_FIFO_ALIGN - 1); |
| |
| if (!dec->chunk->block->is_mapped) |
| data = codec_mm_vmap(dec->chunk->block->start + |
| dec->chunk->offset, size); |
| else |
| data = ((u8 *)dec->chunk->block->start_virt) + |
| dec->chunk->offset; |
| |
| avs3_print(dec, 0, "padding: "); |
| for (jj = padding_size; jj > 0; jj--) |
| avs3_print_cont(dec, |
| 0, |
| "%02x ", *(data - jj)); |
| avs3_print_cont(dec, 0, "data adr %p\n", |
| data); |
| |
| for (jj = 0; jj < size; jj++) { |
| if ((jj & 0xf) == 0) |
| avs3_print(dec, |
| 0, |
| "%06x:", jj); |
| avs3_print_cont(dec, |
| 0, |
| "%02x ", data[jj]); |
| if (((jj + 1) & 0xf) == 0) |
| avs3_print(dec, |
| 0, |
| "\n"); |
| } |
| avs3_print(dec, |
| 0, |
| "\n"); |
| |
| if (!dec->chunk->block->is_mapped) |
| codec_mm_unmap_phyaddr(data); |
| } |
| |
| void wait_shift_byte_search_done(struct AVS3Decoder_s *dec) |
| { |
| u32 shift_byte = READ_VREG(HEVC_SHIFT_BYTE_COUNT); |
| int count = 0; |
| do { |
| usleep_range(1000, 1010); |
| if (shift_byte == READ_VREG(HEVC_SHIFT_BYTE_COUNT)) |
| break; |
| if (count > 200) { |
| avs3_print(dec, |
| 0, "%s timeout count %d vld_rp 0x%x VLD_MEM_VIFIFO_RP 0x%x\n", |
| __func__, count, shift_byte, READ_VREG(HEVC_SHIFT_BYTE_COUNT)); |
| break; |
| } else |
| shift_byte = READ_VREG(HEVC_SHIFT_BYTE_COUNT); |
| count++; |
| } while (1); |
| pr_err("count %d, shift_byte 0x%x\n", count, shift_byte); |
| } |
| void wait_hevc_search_done(struct AVS3Decoder_s *dec) |
| { |
| int count = 0; |
| WRITE_VREG(HEVC_SHIFT_STATUS, 0); |
| while (READ_VREG(HEVC_STREAM_CONTROL) & 0x2) { |
| usleep_range(100, 101); |
| count++; |
| if (count > 100) { |
| avs3_print(dec, 0, "%s timeout\n", __func__); |
| break; |
| } |
| } |
| } |
| |
| static int avs3_wait_alloc_buf(void *args) |
| { |
| struct AVS3Decoder_s *dec = (struct AVS3Decoder_s *)args; |
| struct vdec_s *vdec = hw_to_vdec(dec); |
| |
| init_pic_list(dec, dec->avs3_dec.lcu_size_log2); |
| |
| vdec_up(vdec); |
| |
| return 0; |
| } |
| |
| static void avs3_work_implement(struct AVS3Decoder_s *dec) |
| { |
| struct vdec_s *vdec = hw_to_vdec(dec); |
| struct avs3_decoder *avs3_dec = &dec->avs3_dec; |
| |
| /*if (dec->dec_result == DEC_RESULT_DONE) |
| decoder_trace(dec->trace.decode_time_name, DECODER_WORKER_START, TRACE_BASIC); |
| else if (dec->dec_result == DEC_RESULT_AGAIN) |
| decoder_trace(dec->trace.decode_time_name, DECODER_WORKER_AGAIN, TRACE_BASIC);*/ |
| |
| /* finished decoding one frame or error, |
| * notify vdec core to switch context |
| */ |
| avs3_print(dec, PRINT_FLAG_VDEC_DETAIL, |
| "%s dec_result %d %x %x %x\n", |
| __func__, |
| dec->dec_result, |
| READ_VREG(HEVC_STREAM_LEVEL), |
| READ_VREG(HEVC_STREAM_WR_PTR), |
| READ_VREG(HEVC_STREAM_RD_PTR)); |
| |
| if (((dec->dec_result == DEC_RESULT_GET_DATA) || |
| (dec->dec_result == DEC_RESULT_GET_DATA_RETRY)) |
| && (hw_to_vdec(dec)->next_status != |
| VDEC_STATUS_DISCONNECTED)) { |
| if (!vdec_has_more_input(vdec)) { |
| dec->dec_result = DEC_RESULT_EOS; |
| vdec_schedule_work(&dec->work); |
| return; |
| } |
| |
| if (dec->dec_result == DEC_RESULT_GET_DATA) { |
| avs3_print(dec, PRINT_FLAG_VDEC_STATUS, |
| "%s DEC_RESULT_GET_DATA %x %x %x\n", |
| __func__, |
| READ_VREG(HEVC_STREAM_LEVEL), |
| READ_VREG(HEVC_STREAM_WR_PTR), |
| READ_VREG(HEVC_STREAM_RD_PTR)); |
| vdec_vframe_dirty(vdec, dec->chunk); |
| vdec_clean_input(vdec); |
| } |
| |
| if (get_free_buf_count(dec) >= |
| run_ready_min_buf_num) { |
| int r; |
| int decode_size; |
| r = vdec_prepare_input(vdec, &dec->chunk); |
| if (r < 0) { |
| dec->dec_result = DEC_RESULT_GET_DATA_RETRY; |
| |
| avs3_print(dec, |
| PRINT_FLAG_VDEC_DETAIL, |
| "amvdec_avs3: Insufficient data\n"); |
| |
| vdec_schedule_work(&dec->work); |
| return; |
| } |
| dec->dec_result = DEC_RESULT_NONE; |
| avs3_print(dec, PRINT_FLAG_VDEC_STATUS, |
| "%s: chunk size 0x%x sum 0x%x\n", |
| __func__, r, |
| (debug & PRINT_FLAG_VDEC_STATUS) ? |
| get_data_check_sum(dec, r) : 0 |
| ); |
| if (debug & PRINT_FLAG_VDEC_DATA) |
| dump_data(dec, dec->chunk->size); |
| |
| decode_size = dec->chunk->size + |
| (dec->chunk->offset & (VDEC_FIFO_ALIGN - 1)); |
| |
| WRITE_VREG(HEVC_DECODE_SIZE, |
| READ_VREG(HEVC_DECODE_SIZE) + decode_size); |
| |
| vdec_enable_input(vdec); |
| |
| WRITE_VREG(HEVC_DEC_STATUS_REG, AVS3_ACTION_DONE); |
| |
| start_process_time(dec); |
| |
| } else{ |
| dec->dec_result = DEC_RESULT_GET_DATA_RETRY; |
| |
| avs3_print(dec, PRINT_FLAG_VDEC_DETAIL, |
| "amvdec_avs3: Insufficient data\n"); |
| |
| vdec_schedule_work(&dec->work); |
| } |
| return; |
| } else if (dec->dec_result == DEC_RESULT_DONE) { |
| /* if (!dec->ctx_valid) |
| dec->ctx_valid = 1; */ |
| dec->slice_idx++; |
| dec->frame_count++; |
| dec->process_state = PROC_STATE_INIT; |
| decode_frame_count[dec->index] = dec->frame_count; |
| |
| avs3_print(dec, PRINT_FLAG_VDEC_STATUS, |
| "%s (===> %d) dec_result %d %x %x %x stream crc %x shiftbytes 0x%x decbytes 0x%x\n", |
| __func__, |
| dec->frame_count, |
| dec->dec_result, |
| READ_VREG(HEVC_STREAM_LEVEL), |
| READ_VREG(HEVC_STREAM_WR_PTR), |
| READ_VREG(HEVC_STREAM_RD_PTR), |
| READ_VREG(HEVC_STREAM_CRC), |
| READ_VREG(HEVC_SHIFT_BYTE_COUNT), |
| READ_VREG(HEVC_SHIFT_BYTE_COUNT) - |
| dec->start_shift_bytes |
| ); |
| vdec_vframe_dirty(hw_to_vdec(dec), dec->chunk); |
| } else if (dec->dec_result == DEC_RESULT_AGAIN) { |
| /* |
| stream base: stream buf empty or timeout |
| frame base: vdec_prepare_input fail |
| */ |
| if (!vdec_has_more_input(vdec)) { |
| dec->dec_result = DEC_RESULT_EOS; |
| vdec_schedule_work(&dec->work); |
| return; |
| } |
| } else if (dec->dec_result == DEC_RESULT_EOS) { |
| DEC_CTX *avs3_ctx = &avs3_dec->ctx; |
| avs3_print(dec, 0, |
| "%s: end of stream\n", |
| __func__); |
| dec->eos = 1; |
| if ( dec->avs3_dec.cur_pic != NULL) { |
| check_pic_error(dec, dec->avs3_dec.cur_pic); |
| avs3_bufmgr_post_process(&dec->avs3_dec); |
| } |
| |
| //output all pic; |
| avs3_ctx->info.pic_header.decode_order_index = |
| avs3_ctx->info.pic_header.decode_order_index + DOI_CYCLE_LENGTH; |
| avs3_prepare_display_buf(dec); |
| vdec_vframe_dirty(hw_to_vdec(dec), dec->chunk); |
| } else if (dec->dec_result == DEC_RESULT_FORCE_EXIT) { |
| avs3_print(dec, PRINT_FLAG_VDEC_STATUS, |
| "%s: force exit\n", |
| __func__); |
| if (dec->stat & STAT_VDEC_RUN) { |
| amhevc_stop(); |
| dec->stat &= ~STAT_VDEC_RUN; |
| } |
| |
| if (dec->stat & STAT_ISR_REG) { |
| if (!dec->m_ins_flag) |
| WRITE_VREG(dec->ASSIST_MBOX0_MASK, 0); |
| vdec_free_irq(VDEC_IRQ_0, (void *)dec); |
| dec->stat &= ~STAT_ISR_REG; |
| } |
| } else if (dec->dec_result == DEC_RESULT_WAIT_BUFFER) { |
| pr_err("DEC_RESULT_WAIT_BUFFER in\n"); |
| vdec_post_task(avs3_wait_alloc_buf, dec); |
| dec->pic_list_wait_alloc_done_flag = BUFFER_ALLOCATING; |
| dec->process_state = |
| PROC_STATE_DECODE_AGAIN; |
| } |
| |
| #ifdef NEW_FRONT_BACK_CODE |
| if (!vdec->front_pic_done && (dec->front_back_mode == 1)) { |
| fb_hw_status_clear(true); |
| avs3_print(dec, PRINT_FLAG_VDEC_STATUS, |
| "%s, clear front, status 0x%x, status_back 0x%x\n", |
| __func__, dec->dec_status, dec->dec_status_back); |
| } |
| #endif |
| |
| if (dec->front_back_mode == 1) |
| amhevc_stop_f(); |
| |
| if (dec->stat & STAT_TIMER_ARM) { |
| del_timer_sync(&dec->timer); |
| dec->stat &= ~STAT_TIMER_ARM; |
| } |
| |
| wait_hevc_search_done(dec); |
| |
| if (dec->dec_result == DEC_RESULT_DONE) |
| decoder_trace(dec->trace.decode_time_name, DECODER_WORKER_END, TRACE_PERFORMANCE_DETAIL); |
| |
| /* mark itself has all HW resource released and input released */ |
| if (vdec->parallel_dec ==1) |
| vdec_core_finish_run(vdec, CORE_MASK_HEVC); |
| else |
| vdec_core_finish_run(vdec, CORE_MASK_VDEC_1 | CORE_MASK_HEVC); |
| |
| if (dec->vdec_cb) |
| dec->vdec_cb(hw_to_vdec(dec), dec->vdec_cb_arg, CORE_MASK_HEVC); |
| } |
| |
| static void avs3_work(struct work_struct *work) |
| { |
| struct AVS3Decoder_s *dec = container_of(work, |
| struct AVS3Decoder_s, work); |
| |
| avs3_work_implement(dec); |
| } |
| |
| #ifdef NEW_FB_CODE |
| static void avs3_work_back_implement(struct AVS3Decoder_s *dec, |
| struct vdec_s *vdec, int from) |
| { |
| avs3_print(dec, PRINT_FLAG_VDEC_DETAIL, |
| "[BE] %s result %d\n", __func__, dec->dec_back_result); |
| ATRACE_COUNTER(dec->trace.decode_back_time_name, DECODER_WORKER_START); |
| |
| if (dec->dec_back_result == DEC_BACK_RESULT_TIMEOUT) { |
| u32 j; |
| struct avs3_decoder *avs3_dec = &dec->avs3_dec; |
| avs3_frame_t* pic = avs3_dec->next_be_decode_pic[avs3_dec->fb_rd_pos]; |
| struct avs3_frame_s *ref_pic = NULL; |
| |
| WRITE_VREG(HEVC_DEC_STATUS_DBE, AVS3_DEC_IDLE); |
| amhevc_stop_b(); |
| |
| mutex_lock(&dec->fb_mutex); |
| avs3_dec->backend_decoded_count++; |
| pic->back_done_mark = 1; |
| pic->error_mark = 1; /* set error mark for timeout pic */ |
| pic->backend_ref--; |
| for (j = 0; j < pic->list0_num_refp; j++) { |
| ref_pic = &avs3_dec->pic_pool[pic->list0_index[j]].buf_cfg; |
| ref_pic->backend_ref--; |
| if (ref_pic->backend_ref < 0) { |
| ref_pic->backend_ref = 0; |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, "%s:L0 ref_pic %d backend_ref error\n", __func__, j); |
| } |
| } |
| for (j = 0; j < pic->list1_num_refp; j++) { |
| ref_pic = &avs3_dec->pic_pool[pic->list1_index[j]].buf_cfg; |
| ref_pic->backend_ref--; |
| if (ref_pic->backend_ref < 0) { |
| ref_pic->backend_ref = 0; |
| avs3_print(dec, AVS3_DBG_BUFMGR_DETAIL, "%s:L1 ref_pic %d backend_ref error\n", __func__, j); |
| } |
| } |
| |
| if (debug & AVS3_DBG_PRINT_PIC_LIST) |
| print_pic_pool(avs3_dec, "after dec backend_ref"); |
| |
| avs3_dec->fb_rd_pos++; |
| if (avs3_dec->fb_rd_pos >= dec->fb_ifbuf_num) |
| avs3_dec->fb_rd_pos = 0; |
| |
| avs3_dec->wait_working_buf = 0; |
| avs3_print(dec, PRINT_FLAG_VDEC_DETAIL, |
| "%s timeout fb_wr_pos %d, set next fb_rd_pos %d, set wait_working_buf %d\n", |
| __func__, avs3_dec->fb_wr_pos, avs3_dec->fb_rd_pos, avs3_dec->wait_working_buf); |
| |
| mutex_unlock(&dec->fb_mutex); |
| |
| if (dec->front_back_mode == 1 || |
| dec->front_back_mode == 3) |
| release_free_mmu_buffers(dec); |
| } |
| |
| if (!vdec->back_pic_done && (dec->front_back_mode == 1)) { |
| fb_hw_status_clear(false); |
| avs3_print(dec, PRINT_FLAG_VDEC_STATUS, |
| "%s, clear back, status 0x%x, status_back 0x%x\n", |
| __func__, dec->dec_status, dec->dec_status_back); |
| } |
| |
| if (dec->stat & STAT_TIMER_BACK_ARM) { |
| del_timer_sync(&dec->timer_back); |
| dec->stat &= ~STAT_TIMER_BACK_ARM; |
| } |
| ATRACE_COUNTER(dec->trace.decode_back_time_name, DECODER_WORKER_END); |
| |
| vdec_core_finish_run(vdec, CORE_MASK_HEVC_BACK); |
| |
| if (dec->vdec_back_cb) |
| dec->vdec_back_cb(hw_to_vdec(dec), dec->vdec_back_cb_arg, CORE_MASK_HEVC_BACK); |
| |
| } |
| |
| static void avs3_work_back(struct work_struct *work) |
| { |
| struct AVS3Decoder_s *dec = container_of(work, |
| struct AVS3Decoder_s, work_back); |
| struct vdec_s *vdec = hw_to_vdec(dec); |
| |
| avs3_work_back_implement(dec, vdec, 0); |
| |
| } |
| |
| static void avs3_timeout_work_back(struct work_struct *work) |
| { |
| struct AVS3Decoder_s *dec = container_of(work, |
| struct AVS3Decoder_s, timeout_work_back); |
| struct vdec_s *vdec = hw_to_vdec(dec); |
| |
| if (work_pending(&dec->work_back)) |
| return; |
| dec->timeout_processing_back = 1; |
| avs3_work_back_implement(dec, vdec, 1); |
| } |
| #endif |
| |
| static int avs3_hw_ctx_restore(struct AVS3Decoder_s *dec) |
| { |
| /* new to do ... */ |
| vavs3_prot_init(dec); |
| return 0; |
| } |
| |
| #ifdef NEW_FB_CODE |
| /*run_ready_back*/ |
| static unsigned long check_input_data(struct vdec_s *vdec, unsigned long mask) |
| { |
| struct AVS3Decoder_s *dec = |
| (struct AVS3Decoder_s *)vdec->private; |
| struct avs3_decoder *avs3_dec = &dec->avs3_dec; |
| |
| if (fbdebug_flag & 0x1) |
| return 0; |
| |
| if (dec->timeout_processing_back && |
| (work_pending(&dec->work_back) || |
| work_busy(&dec->work_back) || |
| work_busy(&dec->timeout_work_back) || |
| work_pending(&dec->timeout_work_back))) { |
| avs3_print(dec, PRINT_FLAG_VDEC_STATUS, |
| "avs3 work back pending,not ready for run.\n"); |
| return 0; |
| } |
| dec->timeout_processing_back = 0; |
| if (dec->front_back_mode == 1) { |
| if ((READ_VREG(HEVC_DEC_STATUS_DBE) == AVS3_DEC_IDLE) && |
| ((avs3_dec->fb_wr_pos != avs3_dec->fb_rd_pos) || avs3_dec->wait_working_buf)) |
| return mask; |
| else |
| return 0; |
| } else if (dec->front_back_mode) { |
| if ((avs3_dec->fb_wr_pos != avs3_dec->fb_rd_pos) || avs3_dec->wait_working_buf) |
| return mask; |
| else |
| return 0; |
| } |
| return 0; |
| } |
| #endif |
| |
| static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) |
| { |
| struct AVS3Decoder_s *dec = |
| (struct AVS3Decoder_s *)vdec->private; |
| struct avs3_decoder *avs3_dec = &dec->avs3_dec; |
| int tvp = vdec_secure(hw_to_vdec(dec)) ? |
| CODEC_MM_FLAGS_TVP : 0; |
| unsigned long ret = 0; |
| unsigned int run_ready_case = 0; |
| #if 0 |
| if ((debug & AVS3_DBG_BE_SIMULATE_IRQ) |
| &&(READ_VREG(DEBUG_REG1_DBE) || |
| READ_VREG(HEVC_DEC_STATUS_DBE)== HEVC_BE_DECODE_DATA_DONE)) { |
| pr_info("Simulate BE irq\n"); |
| WRITE_VREG(dec->backend_ASSIST_MBOX0_IRQ_REG, 1); |
| } |
| #endif |
| if (dec->pic_list_wait_alloc_done_flag == BUFFER_ALLOCATING) |
| return 0; |
| |
| if ((fbdebug_flag & 0x2) && |
| dec->front_back_mode && |
| (dec->avs3_dec.cur_pic != NULL) && |
| (dec->avs3_dec.cur_pic->back_done_mark == 0) && |
| dec->next_again_flag == 0) { |
| run_ready_case = 1; |
| avs3_print(dec, |
| PRINT_FLAG_VDEC_DETAIL, "%s case%d\r\n", __func__, run_ready_case); |
| return 0; |
| } |
| |
| if (debug & AVS3_DBG_PIC_LEAK_WAIT) { |
| run_ready_case = 2; |
| avs3_print(dec, |
| PRINT_FLAG_VDEC_DETAIL, "%s case%d\r\n", __func__, run_ready_case); |
| return ret; |
| } |
| #ifdef NEW_FB_CODE |
| if (dec->front_back_mode && avs3_dec->wait_working_buf) { |
| run_ready_case = 3; |
| avs3_print(dec, |
| PRINT_FLAG_VDEC_DETAIL, "%s case%d\r\n", __func__, run_ready_case); |
| return 0xffffffff; |
| } |
| #endif |
| |
| if (dec->eos) { |
| run_ready_case = 4; |
| avs3_print(dec, |
| PRINT_FLAG_VDEC_DETAIL, "%s case%d\r\n", __func__, run_ready_case); |
| return ret; |
| } |
| if (!dec->first_sc_checked) { |
| int size = decoder_mmu_box_sc_check(dec->mmu_box, tvp); |
| #ifdef NEW_FB_CODE |
| /* to do: |
| for dec->mmu_box_1 |
| */ |
| #endif |
| dec->first_sc_checked = 1; |
| avs3_print(dec, 0, "vavs3 cached=%d need_size=%d speed= %d ms\n", |
| size, (dec->need_cache_size >> PAGE_SHIFT), |
| (int)(get_jiffies_64() - dec->sc_start_time) * 1000/HZ); |
| } |
| |
| if (dec->next_again_flag && |
| (!vdec_frame_based(vdec))) { |
| u32 parser_wr_ptr = |
| STBUF_READ(&vdec->vbuf, get_wp); |
| if (parser_wr_ptr >= dec->pre_parser_wr_ptr && |
| (parser_wr_ptr - dec->pre_parser_wr_ptr) < |
| again_threshold) { |
| int r = vdec_sync_input(vdec); |
| run_ready_case = 5; |
| avs3_print(dec, |
| PRINT_FLAG_VDEC_DETAIL, "%s case%d buf lelvel:%x\n", __func__, run_ready_case, r); |
| return 0; |
| } |
| } |
| /* |
| if (vdec_stream_based(vdec) && (dec->pic_list_init_flag == 0) |
| && pre_decode_buf_level != 0) { |
| u32 rp, wp, level; |
| |
| rp = STBUF_READ(&vdec->vbuf, get_rp); |
| wp = STBUF_READ(&vdec->vbuf, get_wp); |
| if (wp < rp) |
| level = vdec->input.size + wp - rp; |
| else |
| level = wp - rp; |
| |
| if (level < pre_decode_buf_level) |
| return 0; |
| } |
| */ |
| |
| if ((dec->pic_list_init_flag == 0) || |
| get_free_buf_count(dec) >= |
| run_ready_min_buf_num) |
| ret = 1; |
| else { |
| avs3_cleanup_useless_pic_buffer_in_pm(avs3_dec); |
| if (get_free_buf_count(dec) >= run_ready_min_buf_num) |
| ret = 1; |
| else |
| run_ready_case = 0; |
| } |
| |
| #ifdef CONSTRAIN_MAX_BUF_NUM |
| if (dec->pic_list_init_flag) { |
| if (run_ready_max_vf_only_num > 0 && |
| get_vf_ref_only_buf_count(dec) >= |
| run_ready_max_vf_only_num |
| ) { |
| run_ready_case = 10; |
| ret = 0; |
| } |
| if (run_ready_display_q_num > 0 && |
| kfifo_len(&dec->display_q) >= |
| run_ready_display_q_num) { |
| run_ready_case = 11; |
| ret = 0; |
| } |
| |
| /*if (run_ready_max_buf_num == 0xff && |
| get_used_buf_count(dec) >= |
| dec->avs3_dec.ref_maxbuffer) { |
| run_ready_case = 12; |
| ret = 0; |
| } else*/ if (run_ready_max_buf_num && |
| get_used_buf_count(dec) >= |
| run_ready_max_buf_num) { |
| run_ready_case = 13; |
| ret = 0; |
| } |
| } |
| #endif |
| if (ret) |
| not_run_ready[dec->index] = 0; |
| else { |
| not_run_ready[dec->index]++; |
| avs3_print(dec, |
| PRINT_FLAG_VDEC_DETAIL, "%s case%d\r\n", __func__, run_ready_case); |
| } |
| |
| if (vdec->parallel_dec == 1) |
| #ifdef NEW_FB_CODE |
| return ret ? mask : mask & ~(CORE_MASK_HEVC); |
| #else |
| return ret ? CORE_MASK_HEVC : 0; |
| #endif |
| else |
| return ret ? (CORE_MASK_VDEC_1 | CORE_MASK_HEVC) : 0; |
| } |
| |
| #ifdef NEW_FB_CODE |
| static void run_back(struct vdec_s *vdec, void (*callback)(struct vdec_s *, void *, int), void *arg) |
| { |
| struct AVS3Decoder_s *dec = |
| (struct AVS3Decoder_s *)vdec->private; |
| int loadr = 0; |
| ATRACE_COUNTER(dec->trace.decode_back_run_time_name, TRACE_RUN_LOADING_FW_START); |
| |
| if (vdec->mc_back_loaded || dec->front_back_mode != 1) { |
| /*firmware have load before, |
| and not changes to another. |
| ignore reload. |
| */ |
| } else { |
| loadr = amhevc_vdec_loadmc_ex(VFORMAT_AVS3, vdec, |
| "avs3_back", dec->fw_back->data); |
| |
| if (loadr < 0) { |
| amhevc_disable(); |
| avs3_print(dec, 0, "AVS3: the %s back fw loading failed, err: %x\n", |
| tee_enabled() ? "TEE" : "local", loadr); |
| dec->dec_back_result = DEC_BACK_RESULT_FORCE_EXIT; |
| vdec_schedule_work(&dec->work_back); |
| return; |
| } |
| |
| //vdec->mc_back_loaded = 1; |
| vdec->mc_back_type = VFORMAT_AVS3; |
| } |
| ATRACE_COUNTER(dec->trace.decode_back_run_time_name, TRACE_RUN_LOADING_FW_END); |
| |
| ATRACE_COUNTER(dec->trace.decode_back_run_time_name, TRACE_RUN_BACK_ALLOC_MMU_START); |
| |
| mod_timer(&dec->timer_back, jiffies); |
| dec->stat |= STAT_TIMER_BACK_ARM; |
| |
| run_count_back[dec->index]++; |
| dec->vdec_back_cb_arg = arg; |
| dec->vdec_back_cb = callback; |
| vdec->back_pic_done = false; |
| //pr_err("run h265_HEVC_back_test\n"); |
| //vdec_post_task(h265_HEVC_back_test, hevc); |
| BackEnd_StartDecoding(dec); |
| |
| start_process_time_back(dec); |
| |
| } |
| |
| #if 0 |
| static void start_front_end_multi_pic_decoding(struct AVS3Decoder_s *dec) |
| { /*multi pictures in one packe*/ |
| struct avs3_decoder *avs3_dec = &dec->avs3_dec; |
| printk("Start FrontEnd Decoding %d\n", avs3_dec->frontend_decoded_count); |
| printk("copy loopbuf to next_bk[%d]\n",avs3_dec->fb_wr_pos); |
| copy_loopbufs_ptr(&avs3_dec->next_bk[avs3_dec->fb_wr_pos], &avs3_dec->fr); |
| |
| if (dec->front_back_mode == 1) |
| config_bufstate_front_hw(avs3_dec); |
| WRITE_VREG(HEVC_DEC_STATUS_REG, AVS3_ACTION_DONE); |
| } |
| #endif |
| #endif |
| |
| static void run(struct vdec_s *vdec, unsigned long mask, |
| void (*callback)(struct vdec_s *, void *, int), void *arg) |
| { |
| struct AVS3Decoder_s *dec = |
| (struct AVS3Decoder_s *)vdec->private; |
| int r; |
| |
| #ifdef NEW_FB_CODE |
| struct avs3_decoder *avs3_dec = &dec->avs3_dec; |
| /*simulation code: if (dec_status == AVS3_DEC_IDLE)*/ |
| avs3_print(dec, PRINT_FLAG_VDEC_DETAIL, "%s(mask = 0x%lx)\n", __func__, mask); |
| if (dec->front_back_mode == 0 || (mask & CORE_MASK_HEVC)) { |
| #endif |
| if (debug & PRINT_FLAG_VDEC_STATUS) |
| WRITE_VREG(HEVC_STREAM_CRC, 0); |
| run_count[dec->index]++; |
| dec->vdec_cb_arg = arg; |
| dec->vdec_cb = callback; |
| vdec->front_pic_done = false; |
| |
| decoder_trace(dec->trace.decode_time_name, DECODER_RUN_START, TRACE_PERFORMANCE_DETAIL); |
| /* dec->chunk = vdec_prepare_input(vdec); */ |
| #ifdef NEW_FRONT_BACK_CODE |
| /*simulation code: if (dec_status == HEVC_DECPIC_DATA_DONE) {*/ |
| if (dec->front_back_mode) { |
| avs3_print(dec, PRINT_FLAG_VDEC_STATUS, |
| "Start FrontEnd Decoding %d\n", avs3_dec->frontend_decoded_count); |
| avs3_print(dec, PRINT_FLAG_VDEC_DETAIL, |
| "copy loopbuf fr to next_bk[fb_wr_pos=%d]\n",avs3_dec->fb_wr_pos); |
| copy_loopbufs_ptr(&avs3_dec->next_bk[avs3_dec->fb_wr_pos], &avs3_dec->fr); |
| |
| if (dec->front_back_mode == 1) |
| amhevc_reset_f(); |
| else |
| hevc_reset_core(vdec); |
| } else |
| #endif |
| { |
| hevc_reset_core(vdec); |
| } |
| if (vdec_stream_based(vdec)) { |
| dec->pre_parser_wr_ptr = |
| STBUF_READ(&vdec->vbuf, get_wp); |
| dec->next_again_flag = 0; |
| } |
| |
| r = vdec_prepare_input(vdec, &dec->chunk); |
| |
| if (r < 0) { |
| input_empty[dec->index]++; |
| |
| dec->dec_result = DEC_RESULT_AGAIN; |
| |
| avs3_print(dec, PRINT_FLAG_VDEC_DETAIL, |
| "ammvdec_avs3: Insufficient data\n"); |
| |
| vdec_schedule_work(&dec->work); |
| return; |
| } |
| |
| input_empty[dec->index] = 0; |
| dec->dec_result = DEC_RESULT_NONE; |
| |
| if (debug) |
| dec->start_shift_bytes = READ_VREG(HEVC_SHIFT_BYTE_COUNT); |
| |
| if (debug & PRINT_FLAG_VDEC_STATUS) { |
| int ii; |
| avs3_print(dec, 0, |
| "%s (%d): size 0x%x (0x%x 0x%x) sum 0x%x (%x %x %x %x %x) bytes 0x%x", |
| __func__, |
| dec->frame_count, r, |
| dec->chunk ? dec->chunk->size : 0, |
| dec->chunk ? dec->chunk->offset : 0, |
| dec->chunk ? ((vdec_frame_based(vdec) && |
| (debug & PRINT_FLAG_VDEC_STATUS)) ? |
| get_data_check_sum(dec, r) : 0) : 0, |
| READ_VREG(HEVC_STREAM_START_ADDR), |
| READ_VREG(HEVC_STREAM_END_ADDR), |
| READ_VREG(HEVC_STREAM_LEVEL), |
| READ_VREG(HEVC_STREAM_WR_PTR), |
| READ_VREG(HEVC_STREAM_RD_PTR), |
| dec->start_shift_bytes); |
| if (vdec_frame_based(vdec) && dec->chunk) { |
| u8 *data = NULL; |
| if (!dec->chunk->block->is_mapped) |
| data = codec_mm_vmap(dec->chunk->block->start + |
| dec->chunk->offset, 8); |
| else |
| data = ((u8 *)dec->chunk->block->start_virt) + |
| dec->chunk->offset; |
| |
| avs3_print_cont(dec, 0, "data adr %p:", |
| data); |
| for (ii = 0; ii < 8; ii++) |
| avs3_print_cont(dec, 0, "%02x ", |
| data[ii]); |
| if (!dec->chunk->block->is_mapped) |
| codec_mm_unmap_phyaddr(data); |
| } |
| avs3_print_cont(dec, 0, "\r\n"); |
| } |
| |
| decoder_trace(dec->trace.decode_run_time_name, TRACE_RUN_LOADING_FW_START, TRACE_BASIC); |
| if (vdec->mc_loaded) { |
| /*firmware have load before, |
| and not changes to another. |
| ignore reload. |
| */ |
| } else { |
| #ifdef NEW_FB_CODE |
| int loadr = 0; |
| if (dec->front_back_mode == 1 || dec->front_back_mode == 3) |
| loadr = amhevc_vdec_loadmc_ex(VFORMAT_AVS3, vdec, |
| "avs3_front", dec->fw->data); |
| else |
| #endif |
| if (amhevc_loadmc_ex(VFORMAT_AVS3, "avs3_mmu", dec->fw->data) < 0) { |
| vdec->mc_loaded = 0; |
| amhevc_disable(); |
| avs3_print(dec, 0, |
| "%s: Error amvdec_loadmc avs3_mmu fail \n", __func__); |
| dec->dec_result = DEC_RESULT_FORCE_EXIT; |
| vdec_schedule_work(&dec->work); |
| return; |
| } |
| //vdec->mc_loaded = 1; |
| vdec->mc_type = VFORMAT_AVS3; |
| } |
| decoder_trace(dec->trace.decode_run_time_name, TRACE_RUN_LOADING_FW_END, TRACE_BASIC); |
| |
| decoder_trace(dec->trace.decode_run_time_name, TRACE_RUN_LOADING_RESTORE_START, TRACE_BASIC); |
| #ifdef NEW_FB_CODE |
| if (dec->front_back_mode) { |
| avs3_hw_init(dec, 1, 0); |
| //config_decode_mode(dec); |
| if (dec->front_back_mode == 1) { |
| config_bufstate_front_hw(avs3_dec); |
| if ((fbdebug_flag & 0x8) && (avs3_dec->frontend_decoded_count == 0)) |
| loop_buffer_fill_zero(dec); |
| } |
| WRITE_VREG(HEVC_DEC_STATUS_REG, AVS3_ACTION_DONE); |
| } else |
| #endif |
| if (avs3_hw_ctx_restore(dec) < 0) { |
| vdec_schedule_work(&dec->work); |
| return; |
| } |
| decoder_trace(dec->trace.decode_run_time_name, TRACE_RUN_LOADING_RESTORE_END, TRACE_BASIC); |
| |
| if (vdec_frame_based(vdec)) |
| WRITE_VREG(HEVC_SHIFT_BYTE_COUNT, 0); |
| |
| vdec_enable_input(vdec); |
| |
| //WRITE_VREG(HEVC_DEC_STATUS_REG, AVS3_SEARCH_NEW_PIC); |
| |
| if (vdec_frame_based(vdec) && dec->chunk) { |
| if (debug & PRINT_FLAG_VDEC_DATA) |
| dump_data(dec, dec->chunk->size); |
| |
| r = dec->chunk->size + |
| (dec->chunk->offset & (VDEC_FIFO_ALIGN - 1)); |
| if (vdec->mvfrm) |
| vdec->mvfrm->frame_size = dec->chunk->size; |
| } |
| |
| WRITE_VREG(HEVC_DECODE_SIZE, r); |
| WRITE_VREG(HEVC_DECODE_COUNT, dec->slice_idx); |
| dec->init_flag = 1; |
| |
| /* |
| avs3_print(dec, PRINT_FLAG_VDEC_DETAIL, |
| "%s: start hevc (%x %x %x)\n", |
| __func__, |
| READ_VREG(HEVC_DEC_STATUS_REG), |
| READ_VREG(HEVC_MPC_E), |
| READ_VREG(HEVC_MPSR)); |
| */ |
| start_process_time(dec); |
| mod_timer(&dec->timer, jiffies); |
| dec->stat |= STAT_TIMER_ARM; |
| dec->stat |= STAT_ISR_REG; |
| if (vdec->mvfrm) |
| vdec->mvfrm->hw_decode_start = local_clock(); |
| #ifdef NEW_FB_CODE |
| if (dec->front_back_mode == 1) |
| amhevc_start_f(); |
| else |
| #endif |
| amhevc_start(); |
| dec->stat |= STAT_VDEC_RUN; |
| decoder_trace(dec->trace.decode_time_name, DECODER_RUN_END, TRACE_PERFORMANCE_DETAIL); |
| #ifdef NEW_FB_CODE |
| } |
| if (dec->front_back_mode && |
| (mask & CORE_MASK_HEVC_BACK)) { |
| ATRACE_COUNTER(dec->trace.decode_back_time_name, DECODER_RUN_START); |
| run_back(vdec, callback, arg); |
| ATRACE_COUNTER(dec->trace.decode_back_time_name, DECODER_RUN_END); |
| } |
| #endif |
| } |
| |
| static void reset(struct vdec_s *vdec) |
| { |
| |
| struct AVS3Decoder_s *dec = |
| (struct AVS3Decoder_s *)vdec->private; |
| |
| avs3_print(dec, |
| PRINT_FLAG_VDEC_DETAIL, "%s\r\n", __func__); |
| |
| } |
| |
| static irqreturn_t avs3_irq_cb(struct vdec_s *vdec, int irq) |
| { |
| struct AVS3Decoder_s *dec = |
| (struct AVS3Decoder_s *)vdec->private; |
| return vavs3_isr(0, dec); |
| } |
| |
| static irqreturn_t avs3_threaded_irq_cb(struct vdec_s *vdec, int irq) |
| { |
| struct AVS3Decoder_s *dec = |
| (struct AVS3Decoder_s *)vdec->private; |
| irqreturn_t ret; |
| //unsigned long flags; |
| //lock_front_back(dec, flags); |
| ret = vavs3_isr_thread_fn(0, dec); |
| //unlock_front_back(dec, flags); |
| #ifdef USE_FRONT_ISR_HANDLE_FOR_BACK |
| if ((dec->dec_status_back != AVS3_DEC_IDLE) || |
| READ_VREG(DEBUG_REG1_DBE)) { |
| ret = vavs3_back_isr_thread_fn(dec); |
| } |
| #endif |
| return ret; |
| } |
| |
| static void avs3_dump_state(struct vdec_s *vdec) |
| { |
| struct AVS3Decoder_s *dec = |
| (struct AVS3Decoder_s *)vdec->private; |
| |
| if (radr != 0) { |
| if (rval != 0) { |
| WRITE_VREG(radr, rval); |
| pr_info("WRITE_VREG(%x,%x)\n", radr, rval); |
| } else |
| pr_info("READ_VREG(%x)=%x\n", radr, READ_VREG(radr)); |
| rval = 0; |
| radr = 0; |
| return; |
| } |
| |
| avs3_print(dec, 0, "====== %s\n", __func__); |
| avs3_print(dec, 0, |
| "width/height (%d/%d), max_pb_size %d\n", |
| dec->avs3_dec.img.width, |
| dec->avs3_dec.img.height, |
| dec->avs3_dec.max_pb_size |
| ); |
| |
| avs3_print(dec, 0, |
| "front_back_mode (%d), is_framebase(%d), eos %d, dec_result 0x%x dec_frm %d disp_frm %d run %d not_run_ready %d input_empty %d\n", |
| dec->front_back_mode, |
| input_frame_based(vdec), |
| dec->eos, |
| dec->dec_result, |
| decode_frame_count[dec->index], |
| display_frame_count[dec->index], |
| run_count[dec->index], |
| not_run_ready[dec->index], |
| input_empty[dec->index] |
| ); |
| |
| if (vf_get_receiver(vdec->vf_provider_name)) { |
| enum receiver_start_e state = |
| vf_notify_receiver(vdec->vf_provider_name, |
| VFRAME_EVENT_PROVIDER_QUREY_STATE, |
| NULL); |
| avs3_print(dec, 0, |
| "\nreceiver(%s) state %d\n", |
| vdec->vf_provider_name, |
| state); |
| } |
| |
| avs3_print(dec, 0, |
| "%s, newq(%d/%d), dispq(%d/%d), vf prepare/get/put (%d/%d/%d), free_buf_count %d (min %d for run_ready)\n", |
| __func__, |
| kfifo_len(&dec->newframe_q), |
| VF_POOL_SIZE, |
| kfifo_len(&dec->display_q), |
| VF_POOL_SIZE, |
| dec->vf_pre_count, |
| dec->vf_get_count, |
| dec->vf_put_count, |
| get_free_buf_count(dec), |
| run_ready_min_buf_num |
| ); |
| |
| print_pic_pool(&dec->avs3_dec, ""); |
| |
| avs3_print(dec, 0, |
| "HEVC_DEC_STATUS_REG=0x%x\n", |
| READ_VREG(HEVC_DEC_STATUS_REG)); |
| avs3_print(dec, 0, |
| "HEVC_MPC_E=0x%x\n", |
| READ_VREG(HEVC_MPC_E)); |
| avs3_print(dec, 0, |
| "DECODE_MODE=0x%x\n", |
| READ_VREG(DECODE_MODE)); |
| avs3_print(dec, 0, |
| "NAL_SEARCH_CTL=0x%x\n", |
| READ_VREG(NAL_SEARCH_CTL)); |
| avs3_print(dec, 0, |
| "HEVC_PARSER_LCU_START=0x%x\n", |
| READ_VREG(HEVC_PARSER_LCU_START)); |
| avs3_print(dec, 0, |
| "HEVC_DECODE_SIZE=0x%x\n", |
| READ_VREG(HEVC_DECODE_SIZE)); |
| avs3_print(dec, 0, |
| "HEVC_SHIFT_BYTE_COUNT=0x%x\n", |
| READ_VREG(HEVC_SHIFT_BYTE_COUNT)); |
| avs3_print(dec, 0, |
| "HEVC_STREAM_START_ADDR=0x%x\n", |
| READ_VREG(HEVC_STREAM_START_ADDR)); |
| avs3_print(dec, 0, |
| "HEVC_STREAM_END_ADDR=0x%x\n", |
| READ_VREG(HEVC_STREAM_END_ADDR)); |
| avs3_print(dec, 0, |
| "HEVC_STREAM_LEVEL=0x%x\n", |
| READ_VREG(HEVC_STREAM_LEVEL)); |
| avs3_print(dec, 0, |
| "HEVC_STREAM_WR_PTR=0x%x\n", |
| READ_VREG(HEVC_STREAM_WR_PTR)); |
| avs3_print(dec, 0, |
| "HEVC_STREAM_RD_PTR=0x%x\n", |
| READ_VREG(HEVC_STREAM_RD_PTR)); |
| avs3_print(dec, 0, |
| "PARSER_VIDEO_RP=0x%x\n", |
| STBUF_READ(&vdec->vbuf, get_rp)); |
| avs3_print(dec, 0, |
| "PARSER_VIDEO_WP=0x%x\n", |
| STBUF_READ(&vdec->vbuf, get_wp)); |
| |
| if (input_frame_based(vdec) && |
| (debug & PRINT_FLAG_VDEC_DATA) |
| ) { |
| int jj; |
| if (dec->chunk && dec->chunk->block && |
| dec->chunk->size > 0) { |
| u8 *data = NULL; |
| if (!dec->chunk->block->is_mapped) |
| data = codec_mm_vmap(dec->chunk->block->start + |
| dec->chunk->offset, dec->chunk->size); |
| else |
| data = ((u8 *)dec->chunk->block->start_virt) + |
| dec->chunk->offset; |
| avs3_print(dec, 0, |
| "frame data size 0x%x\n", |
| dec->chunk->size); |
| for (jj = 0; jj < dec->chunk->size; jj++) { |
| if ((jj & 0xf) == 0) |
| avs3_print(dec, 0, |
| "%06x:", jj); |
| avs3_print_cont(dec, 0, |
| "%02x ", data[jj]); |
| if (((jj + 1) & 0xf) == 0) |
| avs3_print_cont(dec, 0, |
| "\n"); |
| } |
| |
| if (!dec->chunk->block->is_mapped) |
| codec_mm_unmap_phyaddr(data); |
| } |
| } |
| |
| if (dec->front_back_mode == 1) { |
| struct avs3_decoder *avs3_dec = &dec->avs3_dec; |
| avs3_print(dec, 0, |
| "[BE] dec_back_result 0x%x, frontend_decoded_count %d, backend_decoded_count %d, fb_wr_pos %d, fb_rd_pos %d, wait_working_buf %d\n", |
| dec->dec_back_result, |
| avs3_dec->frontend_decoded_count, |
| avs3_dec->backend_decoded_count, |
| avs3_dec->fb_wr_pos, |
| avs3_dec->fb_rd_pos, |
| avs3_dec->wait_working_buf |
| ); |
| |
| avs3_print(dec, 0, |
| "[BE] HEVC_DEC_STATUS_DBE=0x%x\n", |
| READ_VREG(HEVC_DEC_STATUS_DBE)); |
| avs3_print(dec, 0, |
| "[BE] HEVC_MPC_E_DBE=0x%x\n", |
| READ_VREG(HEVC_MPC_E_DBE)); |
| avs3_print(dec, 0, |
| "[BE] HEVC_MPSR_DBE=0x%x\n", |
| READ_VREG(HEVC_MPSR_DBE)); |
| avs3_print(dec, 0, |
| "[BE] DEBUG_REG1_DBE=0x%x\n", |
| READ_VREG(DEBUG_REG1_DBE)); |
| avs3_print(dec, 0, |
| "[BE] DEBUG_REG2_DBE=0x%x\n", |
| READ_VREG(DEBUG_REG2_DBE)); |
| print_loopbufs_adr_size(dec); |
| print_loopbufs_ptr(dec, "fr", &avs3_dec->fr); |
| print_loopbufs_ptr(dec, "bk", &avs3_dec->bk); |
| } |
| |
| if (dump_phy_adr != 0 && dump_phy_size != 0) { |
| dump_or_fill_phy_buffer(dec, dump_phy_adr, dump_phy_size, NULL, 2, NULL); |
| } |
| if (fbdebug_flag & 0x80000000) { |
| dump_loop_buffer(dec, -1, 1); |
| fbdebug_flag &= ~0x80000000; |
| } |
| } |
| |
| static void d_dump(struct AVS3Decoder_s *dec, unsigned int phy_adr, int size, |
| struct file *fp, loff_t *wr_off, u32 * total_check_sum, u8 print_flag) |
| { |
| u8 *vaddr; |
| u32 check_sum = 0; |
| vaddr = codec_mm_vmap(phy_adr, size); |
| if (vaddr) { |
| int i; |
| if (total_check_sum == NULL) { |
| for (i = 0; i < size; i++) |
| vaddr[i] = 0; |
| codec_mm_dma_flush(vaddr, size, DMA_TO_DEVICE); |
| } else { |
| codec_mm_dma_flush(vaddr, size, DMA_FROM_DEVICE); |
| if (fp) { |
| media_write(fp, vaddr, size, wr_off); |
| for (i = 0; i < size; i++) |
| check_sum += vaddr[i]; |
| *total_check_sum += check_sum; |
| } else { |
| for (i = 0; i < size; i++) { |
| if (print_flag) { |
| if ((i & 0xf) == 0) |
| avs3_print_cont(dec, 0, "%08x: ", phy_adr+i); |
| avs3_print_cont(dec, 0, "%02x ", vaddr[i]); |
| } |
| check_sum += vaddr[i]; |
| if (print_flag) { |
| if (((i + 1) & 0xf) == 0) |
| avs3_print_flush(dec); //avs3_print(dec, 0, "\n"); |
| } |
| } |
| *total_check_sum += check_sum; |
| if (print_flag) |
| avs3_print(dec, 0, "check_sum %08x, %08x\n", *total_check_sum, check_sum); |
| } |
| } |
| codec_mm_unmap_phyaddr(vaddr); |
| } else { |
| pr_info("%s codec_mm_vmap fail\n", __func__); |
| } |
| } |
| |
| static void dump_or_fill_phy_buffer(struct AVS3Decoder_s *dec, u32 dump_phy_adr, u32 dump_phy_size, char *file, u8 flag, char *mark) |
| { |
| /* |
| flag: 1, fill zero |
| flag: 2, print data |
| */ |
| loff_t off = 0; |
| int mode = O_CREAT | O_WRONLY | O_TRUNC; |
| struct file *fp = NULL; |
| |
| int dump_size = 1024; |
| int remain_size = dump_phy_size; |
| u32 phy_adr = dump_phy_adr; |
| u32 total_check_sum = 0; |
| |
| if (file) { |
| fp = media_open(file, mode, 0666); |
| } |
| while (remain_size > 0) { |
| if (flag == 1) |
| d_dump(dec, phy_adr, dump_size, NULL, NULL, NULL, 0); |
| else |
| d_dump(dec, phy_adr, dump_size, fp, &off, &total_check_sum, flag == 2); |
| |
| remain_size -= dump_size; |
| phy_adr += dump_size; |
| if (remain_size < dump_size) |
| dump_size = remain_size; |
| //msleep(20); |
| } |
| if (fp) { |
| media_close(fp, current->files); |
| } |
| if (flag == 1) |
| avs3_print(dec, 0, "fill phy mem %s %x (size %x):\n", mark?mark:"", dump_phy_adr, dump_phy_size); |
| else |
| avs3_print(dec, 0, "dump phy mem %s %x (size %x) check_sum %x %s\n", mark?mark:"", dump_phy_adr, dump_phy_size, total_check_sum, file? file:""); |
| } |
| |
| static int ammvdec_avs3_probe(struct platform_device *pdev) |
| { |
| struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; |
| int ret; |
| int config_val; |
| int i; |
| struct vframe_content_light_level_s content_light_level; |
| struct vframe_master_display_colour_s vf_dp; |
| /*struct BUF_s BUF[MAX_BUF_NUM];*/ |
| struct AVS3Decoder_s *dec = NULL; |
| static struct vframe_operations_s vf_tmp_ops; |
| |
| pr_info("%s\n", __func__); |
| |
| if (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T5D) { |
| pr_info("%s, chip id %d is not support avs3\n", |
| __func__, get_cpu_major_id()); |
| return -1; |
| } |
| if (pdata == NULL) { |
| pr_info("\nammvdec_avs3 memory resource undefined.\n"); |
| return -EFAULT; |
| } |
| /*dec = (struct AVS3Decoder_s *)devm_kzalloc(&pdev->dev, |
| sizeof(struct AVS3Decoder_s), GFP_KERNEL);*/ |
| memset(&vf_dp, 0, sizeof(struct vframe_master_display_colour_s)); |
| dec = vzalloc(sizeof(struct AVS3Decoder_s)); |
| if (dec == NULL) { |
| pr_info("\nammvdec_avs3 device data allocation failed\n"); |
| return -ENOMEM; |
| } |
| /* |
| //move to other place after pic_pool is initialized |
| if (pdata->parallel_dec == 1) { |
| int i; |
| for (i = 0; i < MAX_PB_SIZE; i++) { |
| dec->avs3_dec.pic_pool[i].buf_cfg.y_canvas_index = -1; |
| dec->avs3_dec.pic_pool[i].buf_cfg.uv_canvas_index = -1; |
| } |
| } |
| */ |
| pdata->private = dec; |
| pdata->dec_status = vavs3_dec_status; |
| #ifdef I_ONLY_SUPPORT |
| pdata->set_trickmode = vavs3_set_trickmode; |
| #endif |
| pdata->run_ready = run_ready; |
| pdata->run = run; |
| dec->avs3_dec.max_pb_size = MAX_PB_SIZE; //will reconfig later |
| #ifdef NEW_FB_CODE |
| dec->front_back_mode = front_back_mode; |
| dec->fb_ifbuf_num = fb_ifbuf_num; |
| if (dec->fb_ifbuf_num > MAX_FB_IFBUF_NUM) |
| dec->fb_ifbuf_num = MAX_FB_IFBUF_NUM; |
| pdata->check_input_data = NULL; |
| if (dec->front_back_mode) { |
| pdata->check_input_data = check_input_data; |
| pdata->reset = NULL; |
| pdata->back_irq_handler = avs3_back_irq_cb; |
| pdata->back_threaded_irq_handler = avs3_back_threaded_irq_cb; |
| } else |
| #endif |
| pdata->reset = reset; |
| pdata->irq_handler = avs3_irq_cb; |
| pdata->threaded_irq_handler = avs3_threaded_irq_cb; |
| pdata->dump_state = avs3_dump_state; |
| |
| /* |
| * memcpy(&BUF[0], &dec->m_BUF[0], sizeof(struct BUF_s) * MAX_BUF_NUM); |
| * memset(dec, 0, sizeof(struct AVS3Decoder_s)); |
| * memcpy(&dec->m_BUF[0], &BUF[0], sizeof(struct BUF_s) * MAX_BUF_NUM); |
| */ |
| |
| dec->index = pdev->id; |
| dec->m_ins_flag = 1; |
| |
| config_hevc_irq_num(dec); |
| |
| if (is_rdma_enable()) { |
| dec->rdma_adr = decoder_dma_alloc_coherent(&dec->rdma_mem_handle, RDMA_SIZE, &dec->rdma_phy_adr, "AVS3_RDMA_BUF"); |
| for (i = 0; i < SCALELUT_DATA_WRITE_NUM; i++) { |
| dec->rdma_adr[i * 4] = HEVC_IQIT_SCALELUT_WR_ADDR & 0xfff; |
| dec->rdma_adr[i * 4 + 1] = i; |
| dec->rdma_adr[i * 4 + 2] = HEVC_IQIT_SCALELUT_DATA & 0xfff; |
| dec->rdma_adr[i * 4 + 3] = 0; |
| if (i == SCALELUT_DATA_WRITE_NUM - 1) { |
| dec->rdma_adr[i * 4 + 2] = (HEVC_IQIT_SCALELUT_DATA & 0xfff) | 0x20000; |
| } |
| } |
| } |
| |
| snprintf(dec->trace.vdec_name, sizeof(dec->trace.vdec_name), |
| "avs3-%d", dec->index); |
| snprintf(dec->trace.pts_name, sizeof(dec->trace.pts_name), |
| "%s-pts", dec->trace.vdec_name); |
| snprintf(dec->trace.vf_get_name, sizeof(dec->trace.vf_get_name), |
| "%s-vf_get", dec->trace.vdec_name); |
| snprintf(dec->trace.vf_put_name, sizeof(dec->trace.vf_put_name), |
| "%s-vf_put", dec->trace.vdec_name); |
| snprintf(dec->trace.set_canvas0_addr, sizeof(dec->trace.set_canvas0_addr), |
| "%s-set_canvas0_addr", dec->trace.vdec_name); |
| snprintf(dec->trace.get_canvas0_addr, sizeof(dec->trace.get_canvas0_addr), |
| "%s-get_canvas0_addr", dec->trace.vdec_name); |
| snprintf(dec->trace.put_canvas0_addr, sizeof(dec->trace.put_canvas0_addr), |
| "%s-put_canvas0_addr", dec->trace.vdec_name); |
| snprintf(dec->trace.new_q_name, sizeof(dec->trace.new_q_name), |
| "%s-newframe_q", dec->trace.vdec_name); |
| snprintf(dec->trace.disp_q_name, sizeof(dec->trace.disp_q_name), |
| "%s-dispframe_q", dec->trace.vdec_name); |
| snprintf(dec->trace.decode_time_name, sizeof(dec->trace.decode_time_name), |
| "decoder_time%d", pdev->id); |
| snprintf(dec->trace.decode_run_time_name, sizeof(dec->trace.decode_run_time_name), |
| "decoder_run_time%d", pdev->id); |
| snprintf(dec->trace.decode_header_memory_time_name, sizeof(dec->trace.decode_header_memory_time_name), |
| "decoder_header_time%d", pdev->id); |
| snprintf(dec->trace.decode_work_time_name, sizeof(dec->trace.decode_work_time_name), |
| "decoder_work_time%d", pdev->id); |
| snprintf(dec->trace.decode_back_time_name, sizeof(dec->trace.decode_back_time_name), |
| "decoder_back_time%d", pdev->id); |
| snprintf(dec->trace.decode_back_run_time_name, sizeof(dec->trace.decode_back_run_time_name), |
| "decoder_back_run_time%d", pdev->id); |
| snprintf(dec->trace.decode_back_work_time_name, sizeof(dec->trace.decode_back_work_time_name), |
| "decoder_back_work_time%d", pdev->id); |
| |
| if (pdata->use_vfm_path) { |
| snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, |
| VFM_DEC_PROVIDER_NAME); |
| dec->frameinfo_enable = 1; |
| } else |
| snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, |
| MULTI_INSTANCE_PROVIDER_NAME ".%02x", pdev->id & 0xff); |
| |
| memcpy(&vf_tmp_ops, &vavs3_vf_provider, sizeof(struct vframe_operations_s)); |
| if (without_display_mode == 1) { |
| vf_tmp_ops.get = NULL; |
| } |
| vf_provider_init(&pdata->vframe_provider, pdata->vf_provider_name, |
| &vf_tmp_ops, dec); |
| |
| dec->provider_name = pdata->vf_provider_name; |
| platform_set_drvdata(pdev, pdata); |
| |
| dec->platform_dev = pdev; |
| dec->video_signal_type = 0; |
| dec->video_ori_signal_type = 0; |
| if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_TXLX) |
| dec->stat |= VP9_TRIGGER_FRAME_ENABLE; |
| |
| if ((debug & IGNORE_PARAM_FROM_CONFIG) == 0 && pdata->config_len) { |
| /*use ptr config for double_write_mode, etc*/ |
| avs3_print(dec, 0, "pdata->config=%s\n", pdata->config); |
| if (get_config_int(pdata->config, "avs3_double_write_mode", |
| &config_val) == 0) |
| dec->double_write_mode = config_val; |
| else |
| dec->double_write_mode = double_write_mode; |
| |
| if (get_config_int(pdata->config, "parm_v4l_buffer_margin", |
| &config_val) == 0) |
| dec->dynamic_buf_margin = config_val; |
| else |
| dec->dynamic_buf_margin = 0; |
| |
| if (get_config_int(pdata->config, "sidebind_type", |
| &config_val) == 0) |
| dec->sidebind_type = config_val; |
| |
| if (get_config_int(pdata->config, "sidebind_channel_id", |
| &config_val) == 0) |
| dec->sidebind_channel_id = config_val; |
| |
| if (get_config_int(pdata->config, "HDRStaticInfo", |
| &vf_dp.present_flag) == 0 |
| && vf_dp.present_flag == 1) { |
| get_config_int(pdata->config, "mG.x", |
| &vf_dp.primaries[0][0]); |
| get_config_int(pdata->config, "mG.y", |
| &vf_dp.primaries[0][1]); |
| get_config_int(pdata->config, "mB.x", |
| &vf_dp.primaries[1][0]); |
| get_config_int(pdata->config, "mB.y", |
| &vf_dp.primaries[1][1]); |
| get_config_int(pdata->config, "mR.x", |
| &vf_dp.primaries[2][0]); |
| get_config_int(pdata->config, "mR.y", |
| &vf_dp.primaries[2][1]); |
| get_config_int(pdata->config, "mW.x", |
| &vf_dp.white_point[0]); |
| get_config_int(pdata->config, "mW.y", |
| &vf_dp.white_point[1]); |
| get_config_int(pdata->config, "mMaxDL", |
| &vf_dp.luminance[0]); |
| get_config_int(pdata->config, "mMinDL", |
| &vf_dp.luminance[1]); |
| vf_dp.content_light_level.present_flag = 1; |
| get_config_int(pdata->config, "mMaxCLL", |
| &content_light_level.max_content); |
| get_config_int(pdata->config, "mMaxFALL", |
| &content_light_level.max_pic_average); |
| vf_dp.content_light_level = content_light_level; |
| dec->video_signal_type = (1 << 29) |
| | (5 << 26) /* unspecified */ |
| | (0 << 25) /* limit */ |
| | (1 << 24) /* color available */ |
| | (9 << 16) /* 2020 */ |
| | (16 << 8) /* 2084 */ |
| | (9 << 0); /* 2020 */ |
| } |
| dec->vf_dp = vf_dp; |
| } else { |
| /*dec->vavs3_amstream_dec_info.width = 0; |
| dec->vavs3_amstream_dec_info.height = 0; |
| dec->vavs3_amstream_dec_info.rate = 30;*/ |
| dec->double_write_mode = double_write_mode; |
| dec->dynamic_buf_margin = dynamic_buf_num_margin; |
| } |
| video_signal_type = dec->video_signal_type; |
| |
| if (double_write_mode) { |
| dec->double_write_mode = get_double_write_mode(dec); |
| } |
| |
| if ((dec->double_write_mode & 0x10) == 0) |
| dec->mmu_enable = 1; |
| |
| #ifdef AVS3_10B_MMU_DW |
| if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_T5D) { |
| dec->dw_mmu_enable = |
| (get_double_write_mode(dec) & 0x20) ? 1 : 0; |
| } else { |
| dec->dw_mmu_enable = 0; |
| } |
| #endif |
| if (amvdec_avs3_mmu_init(dec) < 0) { |
| pr_err("avs3 alloc bmmu box failed!!\n"); |
| /* devm_kfree(&pdev->dev, (void *)dec); */ |
| vfree((void *)dec); |
| return -1; |
| } |
| dec->cma_alloc_count = PAGE_ALIGN(work_buf_size) / PAGE_SIZE; |
| ret = decoder_bmmu_box_alloc_buf_phy(dec->bmmu_box, WORK_SPACE_BUF_ID, |
| dec->cma_alloc_count * PAGE_SIZE, DRIVER_NAME, |
| &dec->cma_alloc_addr); |
| if (ret < 0) { |
| uninit_mmu_buffers(dec); |
| /* devm_kfree(&pdev->dev, (void *)dec); */ |
| vfree((void *)dec); |
| return ret; |
| } |
| if (!vdec_secure(pdata)) |
| codec_mm_memset(dec->cma_alloc_addr, 0, dec->cma_alloc_count * PAGE_SIZE); |
| |
| dec->buf_start = dec->cma_alloc_addr; |
| dec->buf_size = work_buf_size; |
| |
| dec->init_flag = 0; |
| dec->first_sc_checked = 0; |
| dec->fatal_error = 0; |
| dec->show_frame_num = 0; |
| |
| if (debug) { |
| pr_info("===AVS3 decoder mem resource 0x%lx size 0x%x\n", |
| dec->buf_start, |
| dec->buf_size); |
| } |
| |
| if (pdata->sys_info) { |
| dec->vavs3_amstream_dec_info = *pdata->sys_info; |
| dec->frame_width = dec->vavs3_amstream_dec_info.width; |
| dec->frame_height = dec->vavs3_amstream_dec_info.height; |
| } else { |
| dec->vavs3_amstream_dec_info.width = 0; |
| dec->vavs3_amstream_dec_info.height = 0; |
| dec->vavs3_amstream_dec_info.rate = 30; |
| } |
| |
| dec->endian = HEVC_CONFIG_LITTLE_ENDIAN; |
| if (is_support_vdec_canvas()) |
| dec->endian = HEVC_CONFIG_BIG_ENDIAN; |
| if (endian) |
| dec->endian = endian; |
| |
| dec->cma_dev = pdata->cma_dev; |
| if (vavs3_init(pdata) < 0) { |
| pr_info("\namvdec_avs3 init failed.\n"); |
| avs3_local_uninit(dec); |
| uninit_mmu_buffers(dec); |
| /* devm_kfree(&pdev->dev, (void *)dec); */ |
| vfree((void *)dec); |
| pdata->dec_status = NULL; |
| return -ENODEV; |
| } |
| if (pdata->parallel_dec == 1) { |
| //run only after pic_pool initialzied in vavs3_init() |
| int i; |
| for (i = 0; i < MAX_PB_SIZE; i++) { |
| dec->avs3_dec.pic_pool[i].buf_cfg.y_canvas_index = -1; |
| dec->avs3_dec.pic_pool[i].buf_cfg.uv_canvas_index = -1; |
| } |
| } |
| spin_lock_init(&dec->buffer_lock); |
| spin_lock_init(&dec->front_back_lock); |
| mutex_init(&dec->slice_header_lock); |
| vdec_set_prepare_level(pdata, start_decode_buf_level); |
| hevc_source_changed(VFORMAT_AVS3, |
| 4096, 2048, 60); |
| if (pdata->parallel_dec == 1) { |
| #ifdef NEW_FB_CODE |
| if (dec->front_back_mode) |
| vdec_core_request(pdata, CORE_MASK_HEVC | CORE_MASK_HEVC_BACK); |
| else |
| #endif |
| vdec_core_request(pdata, CORE_MASK_HEVC); |
| } else { |
| vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC |
| | CORE_MASK_COMBINE); |
| } |
| |
| return 0; |
| } |
| |
| static int ammvdec_avs3_remove(struct platform_device *pdev) |
| { |
| struct AVS3Decoder_s *dec = (struct AVS3Decoder_s *) |
| (((struct vdec_s *)(platform_get_drvdata(pdev)))->private); |
| struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; |
| struct avs3_decoder *avs3_dec = &dec->avs3_dec; |
| struct avs3_frame_s *pic; |
| int i; |
| |
| if (debug) |
| pr_info("amvdec_avs3_remove\n"); |
| |
| vmavs3_stop(dec); |
| |
| if (pdata->parallel_dec == 1) { |
| #ifdef NEW_FB_CODE |
| if (dec->front_back_mode) |
| vdec_core_release(hw_to_vdec(dec), CORE_MASK_HEVC | CORE_MASK_HEVC_BACK); |
| else |
| #endif |
| vdec_core_release(hw_to_vdec(dec), CORE_MASK_HEVC); |
| } else |
| vdec_core_release(hw_to_vdec(dec), CORE_MASK_HEVC); |
| |
| vdec_set_status(hw_to_vdec(dec), VDEC_STATUS_DISCONNECTED); |
| if (pdata->parallel_dec == 1) { |
| for (i = 0; i < MAX_PB_SIZE; i++) { |
| pdata->free_canvas_ex(dec->avs3_dec.pic_pool[i].buf_cfg.y_canvas_index, pdata->id); |
| pdata->free_canvas_ex(dec->avs3_dec.pic_pool[i].buf_cfg.uv_canvas_index, pdata->id); |
| } |
| } |
| |
| for (i = 0; i < avs3_dec->max_pb_size; i++) { |
| pic = &avs3_dec->pic_pool[i].buf_cfg; |
| if (pic->used < 0) |
| continue; |
| |
| release_cuva_data(pic); |
| } |
| |
| #ifdef DEBUG_PTS |
| pr_info("pts missed %ld, pts hit %ld, duration %d\n", |
| dec->pts_missed, dec->pts_hit, dec->frame_dur); |
| #endif |
| if (is_rdma_enable()) |
| decoder_dma_free_coherent(dec->rdma_mem_handle, RDMA_SIZE, dec->rdma_adr, dec->rdma_phy_adr); |
| /* devm_kfree(&pdev->dev, (void *)dec); */ |
| vfree((void *)dec); |
| return 0; |
| } |
| |
| static struct platform_driver ammvdec_avs3_driver = { |
| .probe = ammvdec_avs3_probe, |
| .remove = ammvdec_avs3_remove, |
| #ifdef CONFIG_PM |
| .suspend = amvdec_suspend, |
| .resume = amvdec_resume, |
| #endif |
| .driver = { |
| .name = MULTI_DRIVER_NAME, |
| } |
| }; |
| #endif |
| //#ifndef FOR_S5 |
| static struct mconfig avs3_configs[] = { |
| MC_PU32("bit_depth_luma", &bit_depth_luma), |
| MC_PU32("bit_depth_chroma", &bit_depth_chroma), |
| MC_PU32("frame_width", &frame_width), |
| MC_PU32("frame_height", &frame_height), |
| MC_PU32("debug", &debug), |
| MC_PU32("radr", &radr), |
| MC_PU32("rval", &rval), |
| MC_PU32("pop_shorts", &pop_shorts), |
| MC_PU32("dbg_cmd", &dbg_cmd), |
| MC_PU32("dbg_skip_decode_index", &dbg_skip_decode_index), |
| MC_PU32("endian", &endian), |
| MC_PU32("step", &step), |
| MC_PU32("udebug_flag", &udebug_flag), |
| MC_PU32("decode_pic_begin", &decode_pic_begin), |
| MC_PU32("slice_parse_begin", &slice_parse_begin), |
| MC_PU32("i_only_flag", &i_only_flag), |
| MC_PU32("error_handle_policy", &error_handle_policy), |
| MC_PU32("buf_alloc_width", &buf_alloc_width), |
| MC_PU32("buf_alloc_height", &buf_alloc_height), |
| MC_PU32("buf_alloc_depth", &buf_alloc_depth), |
| MC_PU32("buf_alloc_size", &buf_alloc_size), |
| MC_PU32("buffer_mode", &buffer_mode), |
| MC_PU32("buffer_mode_dbg", &buffer_mode_dbg), |
| MC_PU32("max_buf_num", &max_buf_num), |
| MC_PU32("dynamic_buf_num_margin", &dynamic_buf_num_margin), |
| MC_PU32("mem_map_mode", &mem_map_mode), |
| MC_PU32("double_write_mode", &double_write_mode), |
| MC_PU32("enable_mem_saving", &enable_mem_saving), |
| MC_PU32("force_w_h", &force_w_h), |
| MC_PU32("force_fps", &force_fps), |
| MC_PU32("max_decoding_time", &max_decoding_time), |
| MC_PU32("on_no_keyframe_skiped", &on_no_keyframe_skiped), |
| MC_PU32("start_decode_buf_level", &start_decode_buf_level), |
| MC_PU32("decode_timeout_val", &decode_timeout_val), |
| }; |
| static struct mconfig_node avs3_node; |
| //#endif |
| static int __init amvdec_avs3_driver_init_module(void) |
| { |
| |
| #ifdef AVS3_10B_MMU |
| struct BuffInfo_s *p_buf_info; |
| unsigned int bufspec_index = 0; |
| if (force_bufspec) { |
| bufspec_index = force_bufspec & 0xf; |
| pr_info("force buffer spec %d\n", force_bufspec & 0xf); |
| } else { |
| if (vdec_is_support_4k()) { |
| bufspec_index = 2; /* 8k */ |
| } else |
| bufspec_index = 0;/* 1080p */ |
| } |
| p_buf_info = &amvavs3_workbuff_spec[bufspec_index]; |
| pr_info("%s bufspec_index = %d\n", __func__, bufspec_index); |
| init_buff_spec(NULL, p_buf_info); |
| work_buf_size = |
| (p_buf_info->end_adr - p_buf_info->start_adr |
| + 0xffff) & (~0xffff); |
| |
| #endif |
| pr_debug("amvdec_avs3 module init\n"); |
| |
| #ifdef ERROR_HANDLE_DEBUG |
| dbg_nal_skip_flag = 0; |
| dbg_nal_skip_count = 0; |
| #endif |
| udebug_flag = 0; |
| decode_pic_begin = 0; |
| slice_parse_begin = 0; |
| step = 0; |
| buf_alloc_size = 0; |
| if (platform_driver_register(&ammvdec_avs3_driver)) |
| pr_err("failed to register ammvdec_avs3 driver\n"); |
| |
| if (platform_driver_register(&amvdec_avs3_driver)) { |
| pr_err("failed to register amvdec_avs3 driver\n"); |
| return -ENODEV; |
| } |
| if ((get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_G12A) || |
| (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T5D)) { |
| amvdec_avs3_profile.name = "avs3_unsupport"; |
| } else if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_SM1) { |
| if (vdec_is_support_4k()) |
| amvdec_avs3_profile.profile = |
| "4k, 10bit, dwrite, compressed"; |
| else |
| amvdec_avs3_profile.profile = |
| "10bit, dwrite, compressed"; |
| } else { |
| /* cpu id larger than sm1 support 8k */ |
| amvdec_avs3_profile.profile = |
| "8k, 10bit, dwrite, compressed"; |
| } |
| |
| vcodec_profile_register(&amvdec_avs3_profile); |
| amvdec_avs3_profile_mult = amvdec_avs3_profile; |
| amvdec_avs3_profile_mult.name = "mavs3"; |
| vcodec_profile_register(&amvdec_avs3_profile_mult); |
| |
| INIT_REG_NODE_CONFIGS("media.decoder", &avs3_node, |
| "avs3", avs3_configs, CONFIG_FOR_RW); |
| vcodec_feature_register(VFORMAT_AVS3, 0); |
| return 0; |
| } |
| |
| static void __exit amvdec_avs3_driver_remove_module(void) |
| { |
| pr_debug("amvdec_avs3 module remove.\n"); |
| platform_driver_unregister(&ammvdec_avs3_driver); |
| platform_driver_unregister(&amvdec_avs3_driver); |
| } |
| |
| /****************************************/ |
| |
| module_param(bit_depth_luma, uint, 0664); |
| MODULE_PARM_DESC(bit_depth_luma, "\n amvdec_avs3 bit_depth_luma\n"); |
| |
| module_param(bit_depth_chroma, uint, 0664); |
| MODULE_PARM_DESC(bit_depth_chroma, "\n amvdec_avs3 bit_depth_chroma\n"); |
| |
| module_param(frame_width, uint, 0664); |
| MODULE_PARM_DESC(frame_width, "\n amvdec_avs3 frame_width\n"); |
| |
| module_param(frame_height, uint, 0664); |
| MODULE_PARM_DESC(frame_height, "\n amvdec_avs3 frame_height\n"); |
| |
| module_param(debug, uint, 0664); |
| MODULE_PARM_DESC(debug, "\n amvdec_avs3 debug\n"); |
| |
| module_param(debug_again, uint, 0664); |
| MODULE_PARM_DESC(debug_again, "\n amvdec_avs3 debug_again\n"); |
| |
| module_param(radr, uint, 0664); |
| MODULE_PARM_DESC(radr, "\nradr\n"); |
| |
| module_param(rval, uint, 0664); |
| MODULE_PARM_DESC(rval, "\nrval\n"); |
| |
| module_param(pop_shorts, uint, 0664); |
| MODULE_PARM_DESC(pop_shorts, "\nrval\n"); |
| |
| module_param(dbg_cmd, uint, 0664); |
| MODULE_PARM_DESC(dbg_cmd, "\ndbg_cmd\n"); |
| |
| module_param(dbg_skip_decode_index, uint, 0664); |
| MODULE_PARM_DESC(dbg_skip_decode_index, "\ndbg_skip_decode_index\n"); |
| |
| module_param(endian, uint, 0664); |
| MODULE_PARM_DESC(endian, "\nrval\n"); |
| |
| module_param(step, uint, 0664); |
| MODULE_PARM_DESC(step, "\n amvdec_avs3 step\n"); |
| |
| module_param(decode_pic_begin, uint, 0664); |
| MODULE_PARM_DESC(decode_pic_begin, "\n amvdec_avs3 decode_pic_begin\n"); |
| |
| module_param(slice_parse_begin, uint, 0664); |
| MODULE_PARM_DESC(slice_parse_begin, "\n amvdec_avs3 slice_parse_begin\n"); |
| |
| module_param(i_only_flag, uint, 0664); |
| MODULE_PARM_DESC(i_only_flag, "\n amvdec_avs3 i_only_flag\n"); |
| |
| module_param(error_handle_policy, uint, 0664); |
| MODULE_PARM_DESC(error_handle_policy, "\n amvdec_avs3 error_handle_policy\n"); |
| |
| module_param(re_search_seq_threshold, uint, 0664); |
| MODULE_PARM_DESC(re_search_seq_threshold, "\n amvdec_avs3 re_search_seq_threshold\n"); |
| |
| module_param(buf_alloc_width, uint, 0664); |
| MODULE_PARM_DESC(buf_alloc_width, "\n buf_alloc_width\n"); |
| |
| module_param(buf_alloc_height, uint, 0664); |
| MODULE_PARM_DESC(buf_alloc_height, "\n buf_alloc_height\n"); |
| |
| module_param(buf_alloc_depth, uint, 0664); |
| MODULE_PARM_DESC(buf_alloc_depth, "\n buf_alloc_depth\n"); |
| |
| module_param(buf_alloc_size, uint, 0664); |
| MODULE_PARM_DESC(buf_alloc_size, "\n buf_alloc_size\n"); |
| |
| module_param(buffer_mode, uint, 0664); |
| MODULE_PARM_DESC(buffer_mode, "\n buffer_mode\n"); |
| |
| module_param(buffer_mode_dbg, uint, 0664); |
| MODULE_PARM_DESC(buffer_mode_dbg, "\n buffer_mode_dbg\n"); |
| /*USE_BUF_BLOCK*/ |
| module_param(max_buf_num, uint, 0664); |
| MODULE_PARM_DESC(max_buf_num, "\n max_buf_num\n"); |
| |
| module_param(dynamic_buf_num_margin, uint, 0664); |
| MODULE_PARM_DESC(dynamic_buf_num_margin, "\n dynamic_buf_num_margin\n"); |
| |
| #ifdef CONSTRAIN_MAX_BUF_NUM |
| module_param(run_ready_max_vf_only_num, uint, 0664); |
| MODULE_PARM_DESC(run_ready_max_vf_only_num, "\n run_ready_max_vf_only_num\n"); |
| |
| module_param(run_ready_display_q_num, uint, 0664); |
| MODULE_PARM_DESC(run_ready_display_q_num, "\n run_ready_display_q_num\n"); |
| |
| module_param(run_ready_max_buf_num, uint, 0664); |
| MODULE_PARM_DESC(run_ready_max_buf_num, "\n run_ready_max_buf_num\n"); |
| #endif |
| |
| module_param(mv_buf_margin, uint, 0664); |
| MODULE_PARM_DESC(mv_buf_margin, "\n mv_buf_margin\n"); |
| |
| module_param(run_ready_min_buf_num, uint, 0664); |
| MODULE_PARM_DESC(run_ready_min_buf_num, "\n run_ready_min_buf_num\n"); |
| |
| /**/ |
| |
| module_param(mem_map_mode, uint, 0664); |
| MODULE_PARM_DESC(mem_map_mode, "\n mem_map_mode\n"); |
| |
| module_param(double_write_mode, uint, 0664); |
| MODULE_PARM_DESC(double_write_mode, "\n double_write_mode\n"); |
| |
| module_param(enable_mem_saving, uint, 0664); |
| MODULE_PARM_DESC(enable_mem_saving, "\n enable_mem_saving\n"); |
| |
| module_param(force_w_h, uint, 0664); |
| MODULE_PARM_DESC(force_w_h, "\n force_w_h\n"); |
| |
| module_param(force_fps, uint, 0664); |
| MODULE_PARM_DESC(force_fps, "\n force_fps\n"); |
| |
| module_param(max_decoding_time, uint, 0664); |
| MODULE_PARM_DESC(max_decoding_time, "\n max_decoding_time\n"); |
| |
| module_param(on_no_keyframe_skiped, uint, 0664); |
| MODULE_PARM_DESC(on_no_keyframe_skiped, "\n on_no_keyframe_skiped\n"); |
| |
| module_param(start_decode_buf_level, int, 0664); |
| MODULE_PARM_DESC(start_decode_buf_level, |
| "\n avs3 start_decode_buf_level\n"); |
| |
| module_param(decode_timeout_val, uint, 0664); |
| MODULE_PARM_DESC(decode_timeout_val, |
| "\n avs3 decode_timeout_val\n"); |
| |
| module_param_array(decode_frame_count, uint, |
| &max_decode_instance_num, 0664); |
| |
| module_param_array(display_frame_count, uint, |
| &max_decode_instance_num, 0664); |
| |
| module_param_array(max_process_time, uint, |
| &max_decode_instance_num, 0664); |
| |
| module_param_array(run_count, uint, |
| &max_decode_instance_num, 0664); |
| |
| module_param_array(input_empty, uint, |
| &max_decode_instance_num, 0664); |
| |
| module_param_array(not_run_ready, uint, |
| &max_decode_instance_num, 0664); |
| |
| module_param(video_signal_type, uint, 0664); |
| MODULE_PARM_DESC(video_signal_type, "\n amvdec_avs3 video_signal_type\n"); |
| |
| module_param(force_video_signal_type, uint, 0664); |
| MODULE_PARM_DESC(force_video_signal_type, "\n amvdec_avs3 force_video_signal_type\n"); |
| |
| module_param(enable_force_video_signal_type, uint, 0664); |
| MODULE_PARM_DESC(enable_force_video_signal_type, "\n amvdec_avs3 enable_force_video_signal_type\n"); |
| |
| module_param(force_bufspec, uint, 0664); |
| MODULE_PARM_DESC(force_bufspec, "\n amvdec_avs3 force_bufspec\n"); |
| |
| module_param(fbdebug_flag, uint, 0664); |
| MODULE_PARM_DESC(fbdebug_flag, "\n amvdec_avs3 fbdebug_flag\n"); |
| |
| module_param(udebug_flag, uint, 0664); |
| MODULE_PARM_DESC(udebug_flag, "\n amvdec_avs3 udebug_flag\n"); |
| |
| module_param(udebug_pause_pos, uint, 0664); |
| MODULE_PARM_DESC(udebug_pause_pos, "\n udebug_pause_pos\n"); |
| |
| module_param(udebug_pause_val, uint, 0664); |
| MODULE_PARM_DESC(udebug_pause_val, "\n udebug_pause_val\n"); |
| |
| module_param(udebug_pause_decode_idx, uint, 0664); |
| MODULE_PARM_DESC(udebug_pause_decode_idx, "\n udebug_pause_decode_idx\n"); |
| |
| module_param(dump_phy_adr, uint, 0664); |
| MODULE_PARM_DESC(dump_phy_adr, "\n dump_phy_adr\n"); |
| |
| module_param(dump_phy_size, uint, 0664); |
| MODULE_PARM_DESC(dump_phy_size, "\n dump_phy_size\n"); |
| |
| #ifdef DEBUG_CMD |
| module_param(debug_cmd_wait_type, uint, 0664); |
| MODULE_PARM_DESC(debug_cmd_wait_type, "\n debug_cmd_wait_type\n"); |
| |
| module_param(debug_cmd_wait_count, uint, 0664); |
| MODULE_PARM_DESC(debug_cmd_wait_count, "\n debug_cmd_wait_count\n"); |
| #endif |
| |
| module_param(pre_decode_buf_level, int, 0664); |
| MODULE_PARM_DESC(pre_decode_buf_level, |
| "\n amvdec_avs3 pre_decode_buf_level\n"); |
| |
| module_param(again_threshold, uint, 0664); |
| MODULE_PARM_DESC(again_threshold, "\n again_threshold\n"); |
| |
| module_param(force_disp_pic_index, int, 0664); |
| MODULE_PARM_DESC(force_disp_pic_index, |
| "\n amvdec_avs3 force_disp_pic_index\n"); |
| |
| module_param(without_display_mode, uint, 0664); |
| MODULE_PARM_DESC(without_display_mode, "\n without_display_mode\n"); |
| |
| module_param(mv_buf_dynamic_alloc, uint, 0664); |
| MODULE_PARM_DESC(mv_buf_dynamic_alloc, "\n mv_buf_dynamic_alloc\n"); |
| |
| #ifdef NEW_FB_CODE |
| module_param(front_back_mode, uint, 0664); |
| MODULE_PARM_DESC(front_back_mode, "\n amvdec_avs3 front_back_mode\n"); |
| |
| module_param(fb_ifbuf_num, uint, 0664); |
| MODULE_PARM_DESC(fb_ifbuf_num, "\n amvdec_avs3 fb_ifbuf_num\n"); |
| |
| module_param(decode_timeout_val_back, uint, 0664); |
| MODULE_PARM_DESC(decode_timeout_val_back, |
| "\n h265 decode_timeout_val_back\n"); |
| |
| module_param_array(max_process_time_back, uint, |
| &max_decode_instance_num, 0664); |
| #endif |
| |
| module_param(trace_debug_mode, uint, 0664); |
| MODULE_PARM_DESC(trace_debug_mode, "\n trace_debug_mode\n"); |
| |
| module_param(paral_alloc_buffer_mode, uint, 0664); |
| MODULE_PARM_DESC(paral_alloc_buffer_mode, "\n paral_alloc_buffer_mode\n"); |
| |
| #ifdef NEW_FB_CODE |
| |
| module_param(efficiency_mode, uint, 0664); |
| MODULE_PARM_DESC(efficiency_mode, "\n efficiency_mode\n"); |
| |
| #endif |
| |
| module_init(amvdec_avs3_driver_init_module); |
| module_exit(amvdec_avs3_driver_remove_module); |
| |
| MODULE_DESCRIPTION("AMLOGIC avs3 Video Decoder Driver"); |
| MODULE_LICENSE("GPL"); |
| MODULE_AUTHOR("Tim Yao <tim.yao@amlogic.com>"); |