blob: a5d550ff5506b8d6f6be02dc829b0120161cdf88 [file] [log] [blame]
/*
* drivers/amlogic/amports/avs2.c
*
* Copyright (C) 2015 Amlogic, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/semaphore.h>
#include <linux/delay.h>
#include <linux/timer.h>
#include <linux/kfifo.h>
#include <linux/kthread.h>
#include <linux/spinlock.h>
#include <linux/platform_device.h>
#include <linux/amlogic/media/vfm/vframe.h>
#include <linux/amlogic/media/utils/amstream.h>
#include <linux/amlogic/media/utils/vformat.h>
#include <linux/amlogic/media/frame_sync/ptsserv.h>
#include <linux/amlogic/media/frame_sync/tsync.h>
#include <linux/amlogic/media/canvas/canvas.h>
#include <linux/amlogic/media/vfm/vframe_provider.h>
#include <linux/amlogic/media/vfm/vframe_receiver.h>
#include <linux/dma-mapping.h>
#include <linux/dma-contiguous.h>
#include <linux/slab.h>
#include <linux/amlogic/tee.h>
#include "../../../stream_input/amports/amports_priv.h"
#include <linux/amlogic/media/codec_mm/codec_mm.h>
#include "../utils/decoder_mmu_box.h"
#include "../utils/decoder_bmmu_box.h"
#include "avs2_global.h"
#define MEM_NAME "codec_avs2"
/* #include <mach/am_regs.h> */
#include <linux/amlogic/media/utils/vdec_reg.h>
#include "../utils/vdec.h"
#include "../utils/amvdec.h"
#include <linux/amlogic/media/video_sink/video.h>
#include <linux/amlogic/media/codec_mm/configs.h>
#include "../utils/config_parser.h"
#include "../utils/firmware.h"
#include "../../../common/chips/decoder_cpu_ver_info.h"
#include <linux/amlogic/tee.h>
#define I_ONLY_SUPPORT
#define MIX_STREAM_SUPPORT
#define G12A_BRINGUP_DEBUG
#define CONSTRAIN_MAX_BUF_NUM
#include "vavs2.h"
#define HEVC_SHIFT_LENGTH_PROTECT 0x313a
#define HEVC_MPRED_CTRL9 0x325b
#define HEVC_DBLK_CFGD 0x350d
#define HEVC_CM_HEADER_START_ADDR 0x3628
#define HEVC_DBLK_CFGB 0x350b
#define HEVCD_MPP_ANC2AXI_TBL_DATA 0x3464
#define HEVC_SAO_MMU_VH1_ADDR 0x363b
#define HEVC_SAO_MMU_VH0_ADDR 0x363a
/*
* AVS2_DEC_STATUS define
*/
/*internal*/
#define AVS2_DEC_IDLE 0
#define AVS2_SEQUENCE 1
#define AVS2_I_PICTURE 2
#define AVS2_PB_PICTURE 3
#define AVS2_DISCARD_STARTCODE 4
#define AVS2_DISCARD_NAL 4
#define AVS2_SLICE_DECODING 6
#define SWAP_IN_CMD 0x10
#define SWAP_OUT_CMD 0x11
#define SWAP_OUTIN_CMD 0x12
#define SWAP_DONE 0x13
#define SWAP_POST_INIT 0x14
/*head*/
#define AVS2_HEAD_SEQ_READY 0x21
#define AVS2_HEAD_PIC_I_READY 0x22
#define AVS2_HEAD_PIC_PB_READY 0x23
#define AVS2_HEAD_SEQ_END_READY 0x24
#define AVS2_STARTCODE_SEARCH_DONE 0x25
/*pic done*/
#define HEVC_DECPIC_DATA_DONE 0x30
#define HEVC_DECPIC_DATA_ERROR 0x31
#define HEVC_NAL_DECODE_DONE 0x32
#define AVS2_DECODE_BUFEMPTY 0x33
#define AVS2_DECODE_TIMEOUT 0x34
#define AVS2_DECODE_OVER_SIZE 0x35
#define AVS2_EOS 0x36
/*cmd*/
#define AVS2_10B_DISCARD_NAL 0xf0
#define AVS2_SEARCH_NEW_PIC 0xf1
#define AVS2_ACTION_ERROR 0xfe
#define HEVC_ACTION_ERROR 0xfe
#define AVS2_ACTION_DONE 0xff
/*AVS2_DEC_STATUS end*/
#define VF_POOL_SIZE 32
#undef pr_info
#define pr_info printk
#define DECODE_MODE_SINGLE (0 | (0x80 << 24))
#define DECODE_MODE_MULTI_STREAMBASE (1 | (0x80 << 24))
#define DECODE_MODE_MULTI_FRAMEBASE (2 | (0x80 << 24))
#define VP9_TRIGGER_FRAME_DONE 0x100
#define VP9_TRIGGER_FRAME_ENABLE 0x200
/*#define MV_MEM_UNIT 0x240*/
#define MV_MEM_UNIT 0x200
/*---------------------------------------------------
Include "parser_cmd.h"
---------------------------------------------------*/
#define PARSER_CMD_SKIP_CFG_0 0x0000090b
#define PARSER_CMD_SKIP_CFG_1 0x1b14140f
#define PARSER_CMD_SKIP_CFG_2 0x001b1910
#define PARSER_CMD_NUMBER 37
static unsigned short parser_cmd[PARSER_CMD_NUMBER] = {
0x0401,
0x8401,
0x0800,
0x0402,
0x9002,
0x1423,
0x8CC3,
0x1423,
0x8804,
0x9825,
0x0800,
0x04FE,
0x8406,
0x8411,
0x1800,
0x8408,
0x8409,
0x8C2A,
0x9C2B,
0x1C00,
0x840F,
0x8407,
0x8000,
0x8408,
0x2000,
0xA800,
0x8410,
0x04DE,
0x840C,
0x840D,
0xAC00,
0xA000,
0x08C0,
0x08E0,
0xA40E,
0xFC00,
0x7C00
};
static int32_t g_WqMDefault4x4[16] = {
64, 64, 64, 68,
64, 64, 68, 72,
64, 68, 76, 80,
72, 76, 84, 96
};
static int32_t g_WqMDefault8x8[64] = {
64, 64, 64, 64, 68, 68, 72, 76,
64, 64, 64, 68, 72, 76, 84, 92,
64, 64, 68, 72, 76, 80, 88, 100,
64, 68, 72, 80, 84, 92, 100, 112,
68, 72, 80, 84, 92, 104, 112, 128,
76, 80, 84, 92, 104, 116, 132, 152,
96, 100, 104, 116, 124, 140, 164, 188,
104, 108, 116, 128, 152, 172, 192, 216
};
/*#define HEVC_PIC_STRUCT_SUPPORT*/
/* to remove, fix build error */
/*#define CODEC_MM_FLAGS_FOR_VDECODER 0*/
#define MULTI_INSTANCE_SUPPORT
/* #define ERROR_HANDLE_DEBUG */
#ifndef STAT_KTHREAD
#define STAT_KTHREAD 0x40
#endif
#ifdef MULTI_INSTANCE_SUPPORT
#define MAX_DECODE_INSTANCE_NUM 12
#define MULTI_DRIVER_NAME "ammvdec_avs2"
#define lock_buffer(dec, flags) \
spin_lock_irqsave(&dec->buffer_lock, flags)
#define unlock_buffer(dec, flags) \
spin_unlock_irqrestore(&dec->buffer_lock, flags)
static unsigned int max_decode_instance_num
= MAX_DECODE_INSTANCE_NUM;
static unsigned int decode_frame_count[MAX_DECODE_INSTANCE_NUM];
static unsigned int display_frame_count[MAX_DECODE_INSTANCE_NUM];
static unsigned int max_process_time[MAX_DECODE_INSTANCE_NUM];
static unsigned int run_count[MAX_DECODE_INSTANCE_NUM];
static unsigned int input_empty[MAX_DECODE_INSTANCE_NUM];
static unsigned int not_run_ready[MAX_DECODE_INSTANCE_NUM];
#ifdef G12A_BRINGUP_DEBUG
static u32 decode_timeout_val = 200;
#else
static u32 decode_timeout_val = 200;
#endif
static int start_decode_buf_level = 0x8000;
#ifdef AVS2_10B_MMU
static u32 work_buf_size; /* = 24 * 1024 * 1024*/;
#else
static u32 work_buf_size = 32 * 1024 * 1024;
#endif
static u32 mv_buf_margin;
static int pre_decode_buf_level = 0x1000;
static u32 again_threshold;
/* DOUBLE_WRITE_MODE is enabled only when NV21 8 bit output is needed */
/* double_write_mode:
* 0, no double write;
* 1, 1:1 ratio;
* 2, (1/4):(1/4) ratio;
* 3, (1/4):(1/4) ratio, with both compressed frame included
* 4, (1/2):(1/2) ratio;
* 0x10, double write only
* 0x100, if > 1080p,use mode 4,else use mode 1;
* 0x200, if > 1080p,use mode 2,else use mode 1;
* 0x300, if > 720p, use mode 4, else use mode 1;
*/
static u32 double_write_mode;
static u32 without_display_mode;
static u32 mv_buf_dynamic_alloc;
#define DRIVER_NAME "amvdec_avs2"
#define DRIVER_HEADER_NAME "amvdec_avs2_header"
#define PUT_INTERVAL (HZ/100)
#define ERROR_SYSTEM_RESET_COUNT 200
#define PTS_NORMAL 0
#define PTS_NONE_REF_USE_DURATION 1
#define PTS_MODE_SWITCHING_THRESHOLD 3
#define PTS_MODE_SWITCHING_RECOVERY_THREASHOLD 3
#define DUR2PTS(x) ((x)*90/96)
struct AVS2Decoder_s;
static int vavs2_vf_states(struct vframe_states *states, void *);
static struct vframe_s *vavs2_vf_peek(void *);
static struct vframe_s *vavs2_vf_get(void *);
static void vavs2_vf_put(struct vframe_s *, void *);
static int vavs2_event_cb(int type, void *data, void *private_data);
static void set_vframe(struct AVS2Decoder_s *dec,
struct vframe_s *vf, struct avs2_frame_s *pic, u8 dummy);
static int vavs2_stop(struct AVS2Decoder_s *dec);
static s32 vavs2_init(struct vdec_s *vdec);
static void vavs2_prot_init(struct AVS2Decoder_s *dec);
static int vavs2_local_init(struct AVS2Decoder_s *dec);
static void vavs2_put_timer_func(unsigned long arg);
static void dump_data(struct AVS2Decoder_s *dec, int size);
static unsigned char get_data_check_sum
(struct AVS2Decoder_s *dec, int size);
static void dump_pic_list(struct AVS2Decoder_s *dec);
static const char vavs2_dec_id[] = "vavs2-dev";
#define PROVIDER_NAME "decoder.avs2"
#define MULTI_INSTANCE_PROVIDER_NAME "vdec.avs2"
static const struct vframe_operations_s vavs2_vf_provider = {
.peek = vavs2_vf_peek,
.get = vavs2_vf_get,
.put = vavs2_vf_put,
.event_cb = vavs2_event_cb,
.vf_states = vavs2_vf_states,
};
static struct vframe_provider_s vavs2_vf_prov;
static u32 bit_depth_luma;
static u32 bit_depth_chroma;
static u32 frame_width;
static u32 frame_height;
static u32 video_signal_type;
static u32 pts_unstable;
static u32 on_no_keyframe_skiped;
static u32 force_video_signal_type;
static u32 enable_force_video_signal_type;
#define VIDEO_SIGNAL_TYPE_AVAILABLE_MASK 0x20000000
static const char * const video_format_names[] = {
"component", "PAL", "NTSC", "SECAM",
"MAC", "unspecified", "Reserved", "Reserved"
};
static inline int div_r32(int64_t m, int n)
{
/*
return (int)(m/n)
*/
#ifndef CONFIG_ARM64
int64_t qu = 0;
qu = div_s64(m, n);
return (int)qu;
#else
return (int)(m/n);
#endif
}
enum vpx_bit_depth_t {
AVS2_BITS_8 = 8, /**< 8 bits */
AVS2_BITS_10 = 10, /**< 10 bits */
AVS2_BITS_12 = 12, /**< 12 bits */
};
/*USE_BUF_BLOCK*/
struct BUF_s {
int index;
unsigned int alloc_flag;
/*buffer */
unsigned int cma_page_count;
unsigned long alloc_addr;
unsigned long start_adr;
unsigned int size;
unsigned int free_start_adr;
} /*BUF_t */;
struct MVBUF_s {
unsigned long start_adr;
unsigned int size;
int used_flag;
} /*MVBUF_t */;
/* #undef BUFMGR_ONLY to enable hardware configuration */
/*#define TEST_WR_PTR_INC*/
#define WR_PTR_INC_NUM 128
#define SIMULATION
#define DOS_PROJECT
#undef MEMORY_MAP_IN_REAL_CHIP
/*#undef DOS_PROJECT*/
/*#define MEMORY_MAP_IN_REAL_CHIP*/
/*#define BUFFER_MGR_ONLY*/
/*#define CONFIG_HEVC_CLK_FORCED_ON*/
/*#define ENABLE_SWAP_TEST*/
#ifdef AVS2_10B_NV21
#define MEM_MAP_MODE 2 /* 0:linear 1:32x32 2:64x32*/
#else
#define MEM_MAP_MODE 0 /* 0:linear 1:32x32 2:64x32*/
#endif
#ifdef AVS2_10B_NV21
#else
#define LOSLESS_COMPRESS_MODE
#endif
#define DOUBLE_WRITE_YSTART_TEMP 0x02000000
#define DOUBLE_WRITE_CSTART_TEMP 0x02900000
typedef unsigned int u32;
typedef unsigned short u16;
#define AVS2_DBG_BUFMGR 0x01
#define AVS2_DBG_BUFMGR_MORE 0x02
#define AVS2_DBG_BUFMGR_DETAIL 0x04
#define AVS2_DBG_IRQ_EVENT 0x08
#define AVS2_DBG_OUT_PTS 0x10
#define AVS2_DBG_PRINT_SOURCE_LINE 0x20
#define AVS2_DBG_PRINT_PARAM 0x40
#define AVS2_DBG_PRINT_PIC_LIST 0x80
#define AVS2_DBG_SEND_PARAM_WITH_REG 0x100
#define AVS2_DBG_MERGE 0x200
#define AVS2_DBG_DBG_LF_PRINT 0x400
#define AVS2_DBG_REG 0x800
#define AVS2_DBG_PIC_LEAK 0x1000
#define AVS2_DBG_PIC_LEAK_WAIT 0x2000
#define AVS2_DBG_HDR_INFO 0x4000
#define AVS2_DBG_DIS_LOC_ERROR_PROC 0x10000
#define AVS2_DBG_DIS_SYS_ERROR_PROC 0x20000
#define AVS2_DBG_DUMP_PIC_LIST 0x40000
#define AVS2_DBG_TRIG_SLICE_SEGMENT_PROC 0x80000
#define AVS2_DBG_FORCE_UNCOMPRESS 0x100000
#define AVS2_DBG_LOAD_UCODE_FROM_FILE 0x200000
#define AVS2_DBG_FORCE_SEND_AGAIN 0x400000
#define AVS2_DBG_DUMP_DATA 0x800000
#define AVS2_DBG_DUMP_LMEM_BUF 0x1000000
#define AVS2_DBG_DUMP_RPM_BUF 0x2000000
#define AVS2_DBG_CACHE 0x4000000
#define IGNORE_PARAM_FROM_CONFIG 0x8000000
/*MULTI_INSTANCE_SUPPORT*/
#define PRINT_FLAG_ERROR 0
#define PRINT_FLAG_VDEC_STATUS 0x20000000
#define PRINT_FLAG_VDEC_DETAIL 0x40000000
#define PRINT_FLAG_VDEC_DATA 0x80000000
#define PRINT_LINE() \
do { \
if (debug & AVS2_DBG_PRINT_SOURCE_LINE)\
pr_info("%s line %d\n", __func__, __LINE__);\
} while (0)
static u32 debug;
static u32 debug_again;
bool is_avs2_print_param(void)
{
bool ret = false;
if (debug & AVS2_DBG_PRINT_PARAM)
ret = true;
return ret;
}
bool is_avs2_print_bufmgr_detail(void)
{
bool ret = false;
if (debug & AVS2_DBG_BUFMGR_DETAIL)
ret = true;
return ret;
}
static bool is_reset;
/*for debug*/
static u32 force_bufspec;
/*
udebug_flag:
bit 0, enable ucode print
bit 1, enable ucode detail print
bit [31:16] not 0, pos to dump lmem
bit 2, pop bits to lmem
bit [11:8], pre-pop bits for alignment (when bit 2 is 1)
*/
static u32 udebug_flag;
/*
when udebug_flag[1:0] is not 0
udebug_pause_pos not 0,
pause position
*/
static u32 udebug_pause_pos;
/*
when udebug_flag[1:0] is not 0
and udebug_pause_pos is not 0,
pause only when DEBUG_REG2 is equal to this val
*/
static u32 udebug_pause_val;
static u32 udebug_pause_decode_idx;
static u32 force_disp_pic_index;
#define DEBUG_REG
#ifdef DEBUG_REG
static void WRITE_VREG_DBG2(unsigned adr, unsigned val)
{
if (debug & AVS2_DBG_REG)
pr_info("%s(%x, %x)\n", __func__, adr, val);
if (adr != 0)
WRITE_VREG(adr, val);
}
#undef WRITE_VREG
#define WRITE_VREG WRITE_VREG_DBG2
#endif
//#ifdef AVS2_10B_MMU
//#define MMU_COMPRESS_HEADER_SIZE 0x48000
//#define MMU_COMPRESS_8K_HEADER_SIZE 0x48000*4
//#endif
#define MMU_COMPRESS_HEADER_SIZE_1080P 0x10000
#define MMU_COMPRESS_HEADER_SIZE_4K 0x48000
#define MMU_COMPRESS_HEADER_SIZE_8K 0x120000
#define INVALID_IDX -1 /* Invalid buffer index.*/
#define FRAME_BUFFERS (AVS2_MAX_BUFFER_NUM)
#define HEADER_FRAME_BUFFERS (FRAME_BUFFERS)
#define MAX_BUF_NUM (FRAME_BUFFERS)
#define FRAME_CONTEXTS_LOG2 2
#define FRAME_CONTEXTS (1 << FRAME_CONTEXTS_LOG2)
/*buffer + header buffer + workspace*/
#undef MV_USE_FIXED_BUF
#ifdef MV_USE_FIXED_BUF
#define MAX_BMMU_BUFFER_NUM ((FRAME_BUFFERS + HEADER_FRAME_BUFFERS + 1)+1)
#define VF_BUFFER_IDX(n) (n)
#define HEADER_BUFFER_IDX(n) (FRAME_BUFFERS + n+1)
#define WORK_SPACE_BUF_ID (FRAME_BUFFERS + HEADER_FRAME_BUFFERS+1)
#else
#define MAX_BMMU_BUFFER_NUM (((FRAME_BUFFERS*2)+HEADER_FRAME_BUFFERS+1)+1)
#define VF_BUFFER_IDX(n) (n)
#define HEADER_BUFFER_IDX(n) (FRAME_BUFFERS + n+1)
#define MV_BUFFER_IDX(n) ((FRAME_BUFFERS * 2) + n+1)
#define WORK_SPACE_BUF_ID ((FRAME_BUFFERS * 2) + HEADER_FRAME_BUFFERS+1)
#endif
#define CO_MV_BUF_SIZE_1080P 0x3fc00
#define CO_MV_BUF_SIZE_4K 0x120000
#define CO_MV_BUF_SIZE_8K 0x480000
/*
static void set_canvas(struct AVS2Decoder_s *dec,
struct avs2_frame_s *pic);
int avs2_prepare_display_buf(struct AVS2Decoder_s *dec,
int pos);
*/
struct buff_s {
u32 buf_start;
u32 buf_size;
u32 buf_end;
};
struct BuffInfo_s {
u32 max_width;
u32 max_height;
u32 start_adr;
u32 end_adr;
struct buff_s ipp;
struct buff_s sao_abv;
struct buff_s sao_vb;
struct buff_s short_term_rps;
struct buff_s rcs;
struct buff_s sps;
struct buff_s pps;
struct buff_s sao_up;
struct buff_s swap_buf;
struct buff_s swap_buf2;
struct buff_s scalelut;
struct buff_s dblk_para;
struct buff_s dblk_data;
struct buff_s dblk_data2;
#ifdef AVS2_10B_MMU
struct buff_s mmu_vbh;
struct buff_s cm_header;
#endif
struct buff_s mpred_above;
#ifdef MV_USE_FIXED_BUF
struct buff_s mpred_mv;
#endif
struct buff_s rpm;
struct buff_s lmem;
};
#define DEC_RESULT_NONE 0
#define DEC_RESULT_DONE 1
#define DEC_RESULT_AGAIN 2
#define DEC_RESULT_CONFIG_PARAM 3
#define DEC_RESULT_ERROR 4
#define DEC_INIT_PICLIST 5
#define DEC_UNINIT_PICLIST 6
#define DEC_RESULT_GET_DATA 7
#define DEC_RESULT_GET_DATA_RETRY 8
#define DEC_RESULT_EOS 9
#define DEC_RESULT_FORCE_EXIT 10
static void avs2_work(struct work_struct *work);
struct loop_filter_info_n;
struct loopfilter;
struct segmentation;
struct AVS2Decoder_s {
int pic_list_init_flag;
unsigned char index;
spinlock_t buffer_lock;
struct device *cma_dev;
struct platform_device *platform_dev;
void (*vdec_cb)(struct vdec_s *, void *);
void *vdec_cb_arg;
struct vframe_chunk_s *chunk;
int dec_result;
struct work_struct work;
u32 start_shift_bytes;
struct BuffInfo_s work_space_buf_store;
unsigned long buf_start;
u32 buf_size;
u32 cma_alloc_count;
unsigned long cma_alloc_addr;
uint8_t eos;
unsigned long int start_process_time;
unsigned last_lcu_idx;
int decode_timeout_count;
unsigned timeout_num;
int double_write_mode;
unsigned char m_ins_flag;
char *provider_name;
int frame_count;
u32 stat;
struct timer_list timer;
u32 frame_dur;
u32 frame_ar;
u32 vavs2_ratio;
int fatal_error;
uint8_t init_flag;
uint8_t first_sc_checked;
uint8_t process_busy;
#define PROC_STATE_INIT 0
#define PROC_STATE_HEAD_DONE 1
#define PROC_STATE_DECODING 2
#define PROC_STATE_HEAD_AGAIN 3
#define PROC_STATE_DECODE_AGAIN 4
#define PROC_STATE_TEST1 5
uint8_t process_state;
u32 ucode_pause_pos;
int show_frame_num;
#ifndef AVS2_10B_MMU
struct buff_s mc_buf_spec;
#endif
struct dec_sysinfo vavs2_amstream_dec_info;
void *rpm_addr;
void *lmem_addr;
dma_addr_t rpm_phy_addr;
dma_addr_t lmem_phy_addr;
unsigned short *lmem_ptr;
unsigned short *debug_ptr;
#if 1
/*AVS2_10B_MMU*/
void *frame_mmu_map_addr;
dma_addr_t frame_mmu_map_phy_addr;
#endif
unsigned int use_cma_flag;
struct BUF_s m_BUF[MAX_BUF_NUM];
struct MVBUF_s m_mv_BUF[MAX_BUF_NUM];
u32 used_buf_num;
DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE);
DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE);
DECLARE_KFIFO(pending_q, struct vframe_s *, VF_POOL_SIZE);
struct vframe_s vfpool[VF_POOL_SIZE];
u32 vf_pre_count;
u32 vf_get_count;
u32 vf_put_count;
int buf_num;
unsigned int losless_comp_body_size;
u32 video_signal_type;
u32 video_ori_signal_type;
int pts_mode;
int last_lookup_pts;
int last_pts;
u64 last_lookup_pts_us64;
u64 last_pts_us64;
u64 shift_byte_count;
u32 shift_byte_count_lo;
u32 shift_byte_count_hi;
int pts_mode_switching_count;
int pts_mode_recovery_count;
bool get_frame_dur;
u32 saved_resolution;
/**/
int refresh_frame_flags;
uint8_t hold_ref_buf;
struct BuffInfo_s *work_space_buf;
#ifndef AVS2_10B_MMU
struct buff_s *mc_buf;
#endif
unsigned int frame_width;
unsigned int frame_height;
unsigned short *rpm_ptr;
int init_pic_w;
int init_pic_h;
int slice_type;
int decode_idx;
int slice_idx;
uint8_t wait_buf;
uint8_t error_flag;
unsigned int bufmgr_error_count;
/* bit 0, for decoding; bit 1, for displaying */
uint8_t ignore_bufmgr_error;
uint8_t skip_PB_before_I;
int PB_skip_mode;
int PB_skip_count_after_decoding;
/*hw*/
/**/
struct vdec_info *gvs;
unsigned int dec_status;
u32 last_put_idx;
int new_frame_displayed;
void *mmu_box;
void *bmmu_box;
struct vframe_master_display_colour_s vf_dp;
struct firmware_s *fw;
#ifdef AVS2_10B_MMU
int cur_fb_idx_mmu;
long used_4k_num;
#endif
struct avs2_decoder avs2_dec;
#define ALF_NUM_BIT_SHIFT 6
#define NO_VAR_BINS 16
int32_t m_filterCoeffSym[16][9];
int32_t m_varIndTab[NO_VAR_BINS];
struct vframe_s vframe_dummy;
/* start_decoding_flag,
bit 0, SEQ ready
bit 1, I ready
*/
unsigned char start_decoding_flag;
uint32_t mpred_abv_start_addr;
uint32_t mpred_abv_start_addr_bak;
u8 next_again_flag;
u32 pre_parser_wr_ptr;
int need_cache_size;
u64 sc_start_time;
#ifdef I_ONLY_SUPPORT
u32 i_only;
#endif
int frameinfo_enable;
struct vframe_qos_s vframe_qos;
u32 dynamic_buf_margin;
int sidebind_type;
int sidebind_channel_id;
char vdec_name[32];
char pts_name[32];
char new_q_name[32];
char disp_q_name[32];
};
static int compute_losless_comp_body_size(
struct AVS2Decoder_s *dec, int width, int height,
uint8_t is_bit_depth_10);
static int avs2_print(struct AVS2Decoder_s *dec,
int flag, const char *fmt, ...)
{
#define HEVC_PRINT_BUF 256
unsigned char buf[HEVC_PRINT_BUF];
int len = 0;
if (dec == NULL ||
(flag == 0) ||
(debug & flag)) {
va_list args;
va_start(args, fmt);
if (dec)
len = sprintf(buf, "[%d]", dec->index);
vsnprintf(buf + len, HEVC_PRINT_BUF - len, fmt, args);
pr_info("%s", buf);
va_end(args);
}
return 0;
}
static int avs2_print_cont(struct AVS2Decoder_s *dec,
int flag, const char *fmt, ...)
{
unsigned char buf[HEVC_PRINT_BUF];
int len = 0;
if (dec == NULL ||
(flag == 0) ||
(debug & flag)) {
va_list args;
va_start(args, fmt);
vsnprintf(buf + len, HEVC_PRINT_BUF - len, fmt, args);
pr_info("%s", buf);
va_end(args);
}
return 0;
}
#define PROB_SIZE (496 * 2 * 4)
#define PROB_BUF_SIZE (0x5000)
#define COUNT_BUF_SIZE (0x300 * 4 * 4)
/*compute_losless_comp_body_size(4096, 2304, 1) = 18874368(0x1200000)*/
#define MAX_FRAME_4K_NUM 0x1200
#define MAX_FRAME_8K_NUM 0x4800
#define MAX_SIZE_4K (4096 * 2304)
#define IS_8K_SIZE(w, h) (((w) * (h)) > MAX_SIZE_4K)
#define IS_4K_SIZE(w, h) (((w) * (h)) > (1920*1088))
static int get_frame_mmu_map_size(struct AVS2Decoder_s *dec)
{
if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) &&
(IS_8K_SIZE(dec->init_pic_w, dec->init_pic_h)))
return (MAX_FRAME_8K_NUM * 4);
return (MAX_FRAME_4K_NUM * 4);
}
static int get_compress_header_size(struct AVS2Decoder_s *dec)
{
if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) &&
(IS_8K_SIZE(dec->init_pic_w, dec->init_pic_h)))
return MMU_COMPRESS_HEADER_SIZE_8K;
else if (IS_4K_SIZE(dec->init_pic_w, dec->init_pic_h))
return MMU_COMPRESS_HEADER_SIZE_4K;
return MMU_COMPRESS_HEADER_SIZE_1080P;
}
static void reset_process_time(struct AVS2Decoder_s *dec)
{
if (dec->start_process_time) {
unsigned process_time =
1000 * (jiffies - dec->start_process_time) / HZ;
dec->start_process_time = 0;
if (process_time > max_process_time[dec->index])
max_process_time[dec->index] = process_time;
}
}
static void start_process_time(struct AVS2Decoder_s *dec)
{
dec->start_process_time = jiffies;
dec->decode_timeout_count = 0;
dec->last_lcu_idx = 0;
}
static void update_decoded_pic(struct AVS2Decoder_s *dec);
static void timeout_process(struct AVS2Decoder_s *dec)
{
struct avs2_decoder *avs2_dec = &dec->avs2_dec;
struct avs2_frame_s *cur_pic = avs2_dec->hc.cur_pic;
dec->timeout_num++;
amhevc_stop();
avs2_print(dec,
0, "%s decoder timeout\n", __func__);
if (cur_pic)
cur_pic->error_mark = 1;
dec->dec_result = DEC_RESULT_DONE;
update_decoded_pic(dec);
reset_process_time(dec);
vdec_schedule_work(&dec->work);
}
static u32 get_valid_double_write_mode(struct AVS2Decoder_s *dec)
{
return (dec->m_ins_flag &&
((double_write_mode & 0x80000000) == 0)) ?
dec->double_write_mode :
(double_write_mode & 0x7fffffff);
}
static int get_double_write_mode(struct AVS2Decoder_s *dec)
{
u32 valid_dw_mode = get_valid_double_write_mode(dec);
int w = dec->avs2_dec.img.width;
int h = dec->avs2_dec.img.height;
u32 dw = 0x1; /*1:1*/
switch (valid_dw_mode) {
case 0x100:
if (w > 1920 && h > 1088)
dw = 0x4; /*1:2*/
break;
case 0x200:
if (w > 1920 && h > 1088)
dw = 0x2; /*1:4*/
break;
case 0x300:
if (w > 1280 && h > 720)
dw = 0x4; /*1:2*/
break;
default:
dw = valid_dw_mode;
break;
}
return dw;
}
/* for double write buf alloc */
static int get_double_write_mode_init(struct AVS2Decoder_s *dec)
{
u32 valid_dw_mode = get_valid_double_write_mode(dec);
u32 dw;
int w = dec->init_pic_w;
int h = dec->init_pic_h;
dw = 0x1; /*1:1*/
switch (valid_dw_mode) {
case 0x100:
if (w > 1920 && h > 1088)
dw = 0x4; /*1:2*/
break;
case 0x200:
if (w > 1920 && h > 1088)
dw = 0x2; /*1:4*/
break;
case 0x300:
if (w > 1280 && h > 720)
dw = 0x4; /*1:2*/
break;
default:
dw = valid_dw_mode;
break;
}
return dw;
}
static int get_double_write_ratio(struct AVS2Decoder_s *dec,
int dw_mode)
{
int ratio = 1;
if ((dw_mode == 2) ||
(dw_mode == 3))
ratio = 4;
else if (dw_mode == 4)
ratio = 2;
return ratio;
}
//#define MAX_4K_NUM 0x1200
#ifdef AVS2_10B_MMU
int avs2_alloc_mmu(
struct AVS2Decoder_s *dec,
int cur_buf_idx,
int pic_width,
int pic_height,
unsigned short bit_depth,
unsigned int *mmu_index_adr)
{
int bit_depth_10 = (bit_depth == AVS2_BITS_10);
int picture_size;
int cur_mmu_4k_number, max_frame_num;
#ifdef DYNAMIC_ALLOC_HEAD
unsigned long buf_addr;
struct avs2_frame_s *pic = dec->avs2_dec.hc.cur_pic;
if (pic->header_adr == 0) {
if (decoder_bmmu_box_alloc_buf_phy
(dec->bmmu_box,
HEADER_BUFFER_IDX(cur_buf_idx),
get_compress_header_size(dec),
DRIVER_HEADER_NAME,
&buf_addr) < 0){
avs2_print(dec, 0,
"%s malloc compress header failed %d\n",
DRIVER_HEADER_NAME, cur_buf_idx);
dec->fatal_error |= DECODER_FATAL_ERROR_NO_MEM;
return -1;
} else
pic->header_adr = buf_addr;
}
#endif
picture_size = compute_losless_comp_body_size(
dec, pic_width, pic_height,
bit_depth_10);
cur_mmu_4k_number = ((picture_size + (1 << 12) - 1) >> 12);
if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1)
max_frame_num = MAX_FRAME_8K_NUM;
else
max_frame_num = MAX_FRAME_4K_NUM;
if (cur_mmu_4k_number > max_frame_num) {
pr_err("over max !! cur_mmu_4k_number 0x%x width %d height %d\n",
cur_mmu_4k_number, pic_width, pic_height);
return -1;
}
return decoder_mmu_box_alloc_idx(
dec->mmu_box,
cur_buf_idx,
cur_mmu_4k_number,
mmu_index_adr);
}
#endif
#if 0
/*ndef MV_USE_FIXED_BUF*/
static void dealloc_mv_bufs(struct AVS2Decoder_s *dec)
{
int i;
for (i = 0; i < FRAME_BUFFERS; i++) {
if (dec->m_mv_BUF[i].start_adr) {
if (debug)
pr_info(
"dealloc mv buf(%d) adr %ld size 0x%x used_flag %d\n",
i, dec->m_mv_BUF[i].start_adr,
dec->m_mv_BUF[i].size,
dec->m_mv_BUF[i].used_flag);
decoder_bmmu_box_free_idx(
dec->bmmu_box,
MV_BUFFER_IDX(i));
dec->m_mv_BUF[i].start_adr = 0;
dec->m_mv_BUF[i].size = 0;
dec->m_mv_BUF[i].used_flag = 0;
}
}
}
static int alloc_mv_buf(struct AVS2Decoder_s *dec,
int i, int size)
{
int ret = 0;
if (decoder_bmmu_box_alloc_buf_phy
(dec->bmmu_box,
MV_BUFFER_IDX(i), size,
DRIVER_NAME,
&dec->m_mv_BUF[i].start_adr) < 0) {
dec->m_mv_BUF[i].start_adr = 0;
ret = -1;
} else {
dec->m_mv_BUF[i].size = size;
dec->m_mv_BUF[i].used_flag = 0;
ret = 0;
if (debug) {
pr_info(
"MV Buffer %d: start_adr %p size %x\n",
i,
(void *)dec->m_mv_BUF[i].start_adr,
dec->m_mv_BUF[i].size);
}
}
return ret;
}
static int init_mv_buf_list(struct AVS2Decoder_s *dec)
{
int i;
int ret = 0;
int count = FRAME_BUFFERS;
int pic_width = dec->init_pic_w;
int pic_height = dec->init_pic_h;
int lcu_size = 64; /*fixed 64*/
int pic_width_64 = (pic_width + 63) & (~0x3f);
int pic_height_32 = (pic_height + 31) & (~0x1f);
int pic_width_lcu = (pic_width_64 % lcu_size) ?
pic_width_64 / lcu_size + 1
: pic_width_64 / lcu_size;
int pic_height_lcu = (pic_height_32 % lcu_size) ?
pic_height_32 / lcu_size + 1
: pic_height_32 / lcu_size;
int lcu_total = pic_width_lcu * pic_height_lcu;
int size = ((lcu_total * MV_MEM_UNIT) + 0xffff) &
(~0xffff);
if (mv_buf_margin > 0)
count = dec->avs2_dec.ref_maxbuffer + mv_buf_margin;
for (i = 0; i < count; i++) {
if (alloc_mv_buf(dec, i, size) < 0) {
ret = -1;
break;
}
}
return ret;
}
#if 0
static int get_mv_buf(struct AVS2Decoder_s *dec,
struct avs2_frame_s *pic)
{
int i;
int ret = -1;
for (i = 0; i < FRAME_BUFFERS; i++) {
if (dec->m_mv_BUF[i].start_adr &&
dec->m_mv_BUF[i].used_flag == 0) {
dec->m_mv_BUF[i].used_flag = 1;
ret = i;
break;
}
}
if (ret >= 0) {
pic->mv_buf_index = ret;
pic->mpred_mv_wr_start_addr =
(dec->m_mv_BUF[ret].start_adr + 0xffff) &
(~0xffff);
if (debug & AVS2_DBG_BUFMGR_MORE)
pr_info(
"%s => %d (%d) size 0x%x\n",
__func__, ret,
pic->mpred_mv_wr_start_addr,
dec->m_mv_BUF[ret].size);
} else {
pr_info(
"%s: Error, mv buf is not enough\n",
__func__);
}
return ret;
}
static void put_mv_buf(struct AVS2Decoder_s *dec,
struct avs2_frame_s *pic)
{
int i = pic->mv_buf_index;
if (i >= FRAME_BUFFERS) {
if (debug & AVS2_DBG_BUFMGR_MORE)
pr_info(
"%s: index %d beyond range\n",
__func__, i);
return;
}
if (debug & AVS2_DBG_BUFMGR_MORE)
pr_info(
"%s(%d): used_flag(%d)\n",
__func__, i,
dec->m_mv_BUF[i].used_flag);
pic->mv_buf_index = -1;
if (dec->m_mv_BUF[i].start_adr &&
dec->m_mv_BUF[i].used_flag)
dec->m_mv_BUF[i].used_flag = 0;
}
static void put_un_used_mv_bufs(struct AVS2Decoder_s *dec)
{
struct VP9_Common_s *const cm = &dec->common;
struct RefCntBuffer_s *const frame_bufs = cm->buffer_pool->frame_bufs;
int i;
for (i = 0; i < dec->used_buf_num; ++i) {
if ((frame_bufs[i].ref_count == 0) &&
(frame_bufs[i].buf.index != -1) &&
(frame_bufs[i].buf.mv_buf_index >= 0)
)
put_mv_buf(dec, &frame_bufs[i].buf);
}
}
#endif
#endif
static int get_free_buf_count(struct AVS2Decoder_s *dec)
{
struct avs2_decoder *avs2_dec = &dec->avs2_dec;
int i;
int count = 0;
for (i = 0; i < avs2_dec->ref_maxbuffer; i++) {
if ((avs2_dec->fref[i]->imgcoi_ref < -256
#if 0
|| abs(avs2_dec->fref[i]->
imgtr_fwRefDistance - img->tr) >= 128
#endif
) && avs2_dec->fref[i]->is_output == -1
&& avs2_dec->fref[i]->bg_flag == 0
#ifndef NO_DISPLAY
&& avs2_dec->fref[i]->vf_ref == 0
&& avs2_dec->fref[i]->to_prepare_disp == 0
#endif
) {
count++;
}
}
return count;
}
#ifdef CONSTRAIN_MAX_BUF_NUM
static int get_vf_ref_only_buf_count(struct AVS2Decoder_s *dec)
{
struct avs2_decoder *avs2_dec = &dec->avs2_dec;
int i;
int count = 0;
for (i = 0; i < avs2_dec->ref_maxbuffer; i++) {
if ((avs2_dec->fref[i]->imgcoi_ref < -256
#if 0
|| abs(avs2_dec->fref[i]->
imgtr_fwRefDistance - img->tr) >= 128
#endif
) && avs2_dec->fref[i]->is_output == -1
&& avs2_dec->fref[i]->bg_flag == 0
#ifndef NO_DISPLAY
&& avs2_dec->fref[i]->vf_ref > 0
&& avs2_dec->fref[i]->to_prepare_disp == 0
#endif
) {
count++;
}
}
return count;
}
static int get_used_buf_count(struct AVS2Decoder_s *dec)
{
struct avs2_decoder *avs2_dec = &dec->avs2_dec;
int i;
int count = 0;
for (i = 0; i < avs2_dec->ref_maxbuffer; i++) {
if ((avs2_dec->fref[i]->imgcoi_ref >= -256
#if 0
|| abs(avs2_dec->fref[i]->
imgtr_fwRefDistance - img->tr) >= 128
#endif
) || avs2_dec->fref[i]->is_output != -1
|| avs2_dec->fref[i]->bg_flag != 0
#ifndef NO_DISPLAY
|| avs2_dec->fref[i]->vf_ref != 0
|| avs2_dec->fref[i]->to_prepare_disp != 0
#endif
) {
count++;
}
}
return count;
}
#endif
int avs2_bufmgr_init(struct AVS2Decoder_s *dec, struct BuffInfo_s *buf_spec_i,
struct buff_s *mc_buf_i) {
dec->frame_count = 0;
#ifdef AVS2_10B_MMU
dec->used_4k_num = -1;
dec->cur_fb_idx_mmu = INVALID_IDX;
#endif
/* private init */
dec->work_space_buf = buf_spec_i;
#ifndef AVS2_10B_MMU
dec->mc_buf = mc_buf_i;
#endif
dec->rpm_addr = NULL;
dec->lmem_addr = NULL;
dec->use_cma_flag = 0;
dec->decode_idx = 0;
dec->slice_idx = 0;
/*int m_uiMaxCUWidth = 1<<7;*/
/*int m_uiMaxCUHeight = 1<<7;*/
dec->wait_buf = 0;
dec->error_flag = 0;
dec->skip_PB_before_I = 0;
dec->pts_mode = PTS_NORMAL;
dec->last_pts = 0;
dec->last_lookup_pts = 0;
dec->last_pts_us64 = 0;
dec->last_lookup_pts_us64 = 0;
dec->shift_byte_count = 0;
dec->shift_byte_count_lo = 0;
dec->shift_byte_count_hi = 0;
dec->pts_mode_switching_count = 0;
dec->pts_mode_recovery_count = 0;
dec->buf_num = 0;
dec->bufmgr_error_count = 0;
return 0;
}
#define HEVC_CM_BODY_START_ADDR 0x3626
#define HEVC_CM_BODY_LENGTH 0x3627
#define HEVC_CM_HEADER_LENGTH 0x3629
#define HEVC_CM_HEADER_OFFSET 0x362b
#define LOSLESS_COMPRESS_MODE
/*#define DECOMP_HEADR_SURGENT*/
static u32 mem_map_mode; /* 0:linear 1:32x32 2:64x32 ; m8baby test1902 */
static u32 enable_mem_saving = 1;
static u32 force_w_h;
static u32 force_fps;
const u32 avs2_version = 201602101;
static u32 debug;
static u32 radr;
static u32 rval;
static u32 pop_shorts;
static u32 dbg_cmd;
static u32 dbg_skip_decode_index;
static u32 endian = 0xff0;
#ifdef ERROR_HANDLE_DEBUG
static u32 dbg_nal_skip_flag;
/* bit[0], skip vps; bit[1], skip sps; bit[2], skip pps */
static u32 dbg_nal_skip_count;
#endif
/*for debug*/
static u32 decode_pic_begin;
static uint slice_parse_begin;
static u32 step;
#ifdef MIX_STREAM_SUPPORT
static u32 buf_alloc_width = 4096;
static u32 buf_alloc_height = 2304;
static u32 dynamic_buf_num_margin;
#else
static u32 buf_alloc_width;
static u32 buf_alloc_height;
static u32 dynamic_buf_num_margin = 7;
#endif
#ifdef CONSTRAIN_MAX_BUF_NUM
static u32 run_ready_max_vf_only_num;
static u32 run_ready_display_q_num;
/*0: not check
0xff: avs2_dec.ref_maxbuffer
*/
static u32 run_ready_max_buf_num = 0xff;
#endif
static u32 buf_alloc_depth = 10;
static u32 buf_alloc_size;
/*
bit[0]: 0,
bit[1]: 0, always release cma buffer when stop
bit[1]: 1, never release cma buffer when stop
bit[0]: 1, when stop, release cma buffer if blackout is 1;
do not release cma buffer is blackout is not 1
bit[2]: 0, when start decoding, check current displayed buffer
(only for buffer decoded by vp9) if blackout is 0
1, do not check current displayed buffer
bit[3]: 1, if blackout is not 1, do not release current
displayed cma buffer always.
*/
/* set to 1 for fast play;
set to 8 for other case of "keep last frame"
*/
static u32 buffer_mode = 1;
/* buffer_mode_dbg: debug only*/
static u32 buffer_mode_dbg = 0xffff0000;
/**/
/*
bit 0, 1: only display I picture;
bit 1, 1: only decode I picture;
*/
static u32 i_only_flag;
static u32 max_decoding_time;
/*
error handling
*/
/*error_handle_policy:
bit 0: search seq again if buffer mgr error occur
(buffer mgr error count need big than
re_search_seq_threshold)
bit 1: 1, display from I picture;
0, display from any correct pic
*/
static u32 error_handle_policy = 1;
/*
re_search_seq_threshold:
bit 7~0: buffer mgr error research seq count
bit 15~8: frame count threshold
*/
static u32 re_search_seq_threshold = 0x800; /*0x8;*/
/*static u32 parser_sei_enable = 1;*/
static u32 max_buf_num = (REF_BUFFER + 1);
static u32 run_ready_min_buf_num = 2;
static DEFINE_MUTEX(vavs2_mutex);
#define HEVC_DEC_STATUS_REG HEVC_ASSIST_SCRATCH_0
#define HEVC_RPM_BUFFER HEVC_ASSIST_SCRATCH_1
#define AVS2_ALF_SWAP_BUFFER HEVC_ASSIST_SCRATCH_2
#define HEVC_RCS_BUFFER HEVC_ASSIST_SCRATCH_3
#define HEVC_SPS_BUFFER HEVC_ASSIST_SCRATCH_4
#define HEVC_PPS_BUFFER HEVC_ASSIST_SCRATCH_5
//#define HEVC_SAO_UP HEVC_ASSIST_SCRATCH_6
#ifdef AVS2_10B_MMU
#define AVS2_MMU_MAP_BUFFER HEVC_ASSIST_SCRATCH_7
#else
#define HEVC_STREAM_SWAP_BUFFER HEVC_ASSIST_SCRATCH_7
#endif
#define HEVC_STREAM_SWAP_BUFFER2 HEVC_ASSIST_SCRATCH_8
/*
#define VP9_PROB_SWAP_BUFFER HEVC_ASSIST_SCRATCH_9
#define VP9_COUNT_SWAP_BUFFER HEVC_ASSIST_SCRATCH_A
#define VP9_SEG_MAP_BUFFER HEVC_ASSIST_SCRATCH_B
*/
//#define HEVC_SCALELUT HEVC_ASSIST_SCRATCH_D
#define HEVC_WAIT_FLAG HEVC_ASSIST_SCRATCH_E
#define RPM_CMD_REG HEVC_ASSIST_SCRATCH_F
#define LMEM_DUMP_ADR HEVC_ASSIST_SCRATCH_9
#define HEVC_STREAM_SWAP_TEST HEVC_ASSIST_SCRATCH_L
/*!!!*/
#define HEVC_DECODE_COUNT HEVC_ASSIST_SCRATCH_M
#define HEVC_DECODE_SIZE HEVC_ASSIST_SCRATCH_N
#define DEBUG_REG1 HEVC_ASSIST_SCRATCH_G
#define DEBUG_REG2 HEVC_ASSIST_SCRATCH_H
/*
ucode parser/search control
bit 0: 0, header auto parse; 1, header manual parse
bit 1: 0, auto skip for noneseamless stream; 1, no skip
bit [3:2]: valid when bit1==0;
0, auto skip nal before first vps/sps/pps/idr;
1, auto skip nal before first vps/sps/pps
2, auto skip nal before first vps/sps/pps,
and not decode until the first I slice (with slice address of 0)
3, auto skip before first I slice (nal_type >=16 && nal_type<=21)
bit [15:4] nal skip count (valid when bit0 == 1 (manual mode) )
bit [16]: for NAL_UNIT_EOS when bit0 is 0:
0, send SEARCH_DONE to arm ; 1, do not send SEARCH_DONE to arm
bit [17]: for NAL_SEI when bit0 is 0:
0, do not parse SEI in ucode; 1, parse SEI in ucode
bit [31:20]: used by ucode for debug purpose
*/
#define NAL_SEARCH_CTL HEVC_ASSIST_SCRATCH_I
/*DECODE_MODE: set before start decoder
bit 7~0: decode mode
bit 23~16: start_decoding_flag
bit [0] - SEQ_ready
bit [2:1] - I Picture Count
bit 31~24: chip feature
*/
#define DECODE_MODE HEVC_ASSIST_SCRATCH_J
#define DECODE_STOP_POS HEVC_ASSIST_SCRATCH_K
/*read only*/
#define CUR_NAL_UNIT_TYPE HEVC_ASSIST_SCRATCH_J
#define RPM_BUF_SIZE (0x600 * 2)
#define LMEM_BUF_SIZE (0x600 * 2)
/*mmu_vbh buf is used by HEVC_SAO_MMU_VH0_ADDR, HEVC_SAO_MMU_VH1_ADDR*/
#define VBH_BUF_SIZE_1080P 0x3000
#define VBH_BUF_SIZE_4K 0x5000
#define VBH_BUF_SIZE_8K 0xa000
#define VBH_BUF_SIZE(bufspec) (bufspec->mmu_vbh.buf_size / 2)
/*mmu_vbh_dw buf is used by HEVC_SAO_MMU_VH0_ADDR2,HEVC_SAO_MMU_VH1_ADDR2,
HEVC_DW_VH0_ADDDR, HEVC_DW_VH1_ADDDR*/
#define DW_VBH_BUF_SIZE_1080P (VBH_BUF_SIZE_1080P * 2)
#define DW_VBH_BUF_SIZE_4K (VBH_BUF_SIZE_4K * 2)
#define DW_VBH_BUF_SIZE_8K (VBH_BUF_SIZE_8K * 2)
#define DW_VBH_BUF_SIZE(bufspec) (bufspec->mmu_vbh_dw.buf_size / 4)
#define WORK_BUF_SPEC_NUM 3
static struct BuffInfo_s amvavs2_workbuff_spec[WORK_BUF_SPEC_NUM] = {
{
/* 8M bytes */
.max_width = 1920,
.max_height = 1088,
.ipp = {
/* IPP work space calculation :
4096 * (Y+CbCr+Flags) = 12k, round to 16k */
.buf_size = 0x1e00,
},
.sao_abv = {
.buf_size = 0,
},
.sao_vb = {
.buf_size = 0,
},
.short_term_rps = {
/* SHORT_TERM_RPS - Max 64 set, 16 entry every set,
total 64x16x2 = 2048 bytes (0x800) */
.buf_size = 0x800,
},
.rcs = {
/* RCS STORE AREA - Max 32 RCS, each has 32 bytes,
total 0x0400 bytes */
.buf_size = 0x400,
},
.sps = {
/* SPS STORE AREA - Max 16 SPS, each has 0x80 bytes,
total 0x0800 bytes*/
.buf_size = 0x800,
},
.pps = {
/*PPS STORE AREA - Max 64 PPS, each has 0x80 bytes,
total 0x2000 bytes*/
.buf_size = 0x2000,
},
.sao_up = {
/* SAO UP STORE AREA - Max 640(10240/16) LCU,
each has 16 bytes total 0x2800 bytes */
.buf_size = 0,
},
.swap_buf = {
/* 256cyclex64bit = 2K bytes 0x800
(only 144 cycles valid) */
.buf_size = 0x800,
},
.swap_buf2 = {
.buf_size = 0x800,
},
.scalelut = {
/* support up to 32 SCALELUT 1024x32 =
32Kbytes (0x8000) */
.buf_size = 0,
},
.dblk_para = {
/* DBLK -> Max 256(4096/16) LCU,
each para 1024bytes(total:0x40000),
data 1024bytes(total:0x40000)*/
.buf_size = 0x3d00, //0x3c80,
},
.dblk_data = {
.buf_size = 0x62800,
},
.dblk_data2 = {
.buf_size = 0x62800,
},
#ifdef AVS2_10B_MMU
.mmu_vbh = {
.buf_size = VBH_BUF_SIZE_1080P, /*2*16*(more than 2304)/4, 4K*/
},
#if 0
.cm_header = {
/*add one for keeper.*/
.buf_size = MMU_COMPRESS_HEADER_SIZE *
(FRAME_BUFFERS + 1),
/* 0x44000 = ((1088*2*1024*4)/32/4)*(32/8) */
},
#endif
#endif
.mpred_above = {
.buf_size = 0x1e00, /* 2 * size of hevc*/
},
#ifdef MV_USE_FIXED_BUF
.mpred_mv = {/* 1080p, 0x40000 per buffer */
.buf_size = CO_MV_BUF_SIZE_1080P * FRAME_BUFFERS,
},
#endif
.rpm = {
.buf_size = RPM_BUF_SIZE,
},
.lmem = {
.buf_size = 0x400 * 2,
}
},
{
.max_width = 4096,
.max_height = 2304,
.ipp = {
/* IPP work space calculation :
4096 * (Y+CbCr+Flags) = 12k, round to 16k */
.buf_size = 0x4000,
},
.sao_abv = {
.buf_size = 0,
},
.sao_vb = {
.buf_size = 0,
},
.short_term_rps = {
/* SHORT_TERM_RPS - Max 64 set, 16 entry every set,
total 64x16x2 = 2048 bytes (0x800) */
.buf_size = 0x800,
},
.rcs = {
/* RCS STORE AREA - Max 16 RCS, each has 32 bytes,
total 0x0400 bytes */
.buf_size = 0x400,
},
.sps = {
/* SPS STORE AREA - Max 16 SPS, each has 0x80 bytes,
total 0x0800 bytes */
.buf_size = 0x800,
},
.pps = {
/* PPS STORE AREA - Max 64 PPS, each has 0x80 bytes,
total 0x2000 bytes */
.buf_size = 0x2000,
},
.sao_up = {
/* SAO UP STORE AREA - Max 640(10240/16) LCU,
each has 16 bytes total 0x2800 bytes */
.buf_size = 0,
},
.swap_buf = {
/* 256cyclex64bit = 2K bytes 0x800
(only 144 cycles valid) */
.buf_size = 0x800,
},
.swap_buf2 = {
.buf_size = 0x800,
},
.scalelut = {
/* support up to 32 SCALELUT 1024x32 = 32Kbytes
(0x8000) */
.buf_size = 0,
},
.dblk_para = {
/* DBLK -> Max 256(4096/16) LCU,
each para 1024bytes(total:0x40000),
data 1024bytes(total:0x40000)*/
.buf_size = 0x8100, //0x8080,
},
.dblk_data = {
/*DBLK -> Max 256(4096/16) LCU,
each para 1024bytes(total:0x40000),
data 1024bytes(total:0x40000)*/
.buf_size = 0x88800,
},
.dblk_data2 = {
.buf_size = 0x88800,
},
#ifdef AVS2_10B_MMU
.mmu_vbh = {
.buf_size = VBH_BUF_SIZE_4K,/*2*16*(more than 2304)/4, 4K*/
},
#if 0
.cm_header = {
/*add one for keeper.*/
.buf_size = MMU_COMPRESS_HEADER_SIZE *
(FRAME_BUFFERS + 1),
/* 0x44000 = ((1088*2*1024*4)/32/4)*(32/8) */
},
#endif
#endif
.mpred_above = {
.buf_size = 0x4000, /* 2 * size of hevc*/
},
#ifdef MV_USE_FIXED_BUF
.mpred_mv = {
/* .buf_size = 0x100000*16,
//4k2k , 0x100000 per buffer */
/* 4096x2304 , 0x120000 per buffer */
.buf_size = CO_MV_BUF_SIZE_4K * FRAME_BUFFERS,
},
#endif
.rpm = {
.buf_size = RPM_BUF_SIZE,
},
.lmem = {
.buf_size = 0x400 * 2,
}
},
{
.max_width = 4096 * 2,
.max_height = 2304 * 2,
.ipp = {
/*IPP work space calculation : 4096 * (Y+CbCr+Flags) = 12k,
round to 16k*/
.buf_size = 0x4000 * 2,
},
.sao_abv = {
.buf_size = 0,
},
.sao_vb = {
.buf_size = 0,
},
.short_term_rps = {
/*SHORT_TERM_RPS - Max 64 set, 16 entry every set,
total 64x16x2 = 2048 bytes (0x800)*/
.buf_size = 0x800,
},
.rcs = {
/*RCS STORE AREA - Max 16 RCS, each has 32 bytes,
total 0x0400 bytes*/
.buf_size = 0x400,
},
.sps = {
/*SPS STORE AREA - Max 16 SPS, each has 0x80 bytes,
total 0x0800 bytes*/
.buf_size = 0x800,
},
.pps = {
/*PPS STORE AREA - Max 64 PPS, each has 0x80 bytes, total
0x2000 bytes*/
.buf_size = 0x2000,
},
.sao_up = {
/*SAO UP STORE AREA - Max 640(10240/16) LCU, each has 16 bytes i
total 0x2800 bytes*/
.buf_size = 0,
},
.swap_buf = {
/*256cyclex64bit = 2K bytes 0x800 (only 144 cycles valid)*/
.buf_size = 0x800,
},
.swap_buf2 = {
.buf_size = 0x800,
},
.scalelut = {
/*support up to 32 SCALELUT 1024x32 = 32Kbytes (0x8000)*/
.buf_size = 0,
},
.dblk_para = {
.buf_size = 0x10100, //0x10080,
},
.dblk_data = {
.buf_size = 0x110800,
},
.dblk_data2 = {
.buf_size = 0x110800,
},
#ifdef AVS2_10B_MMU
.mmu_vbh = {
.buf_size = VBH_BUF_SIZE_8K, /*2*16*2304/4, 4K*/
},
#if 0
.cm_header = {
/*0x44000 = ((1088*2*1024*4)/32/4)*(32/8)*/
.buf_size = MMU_COMPRESS_8K_HEADER_SIZE * 17,
},
#endif
#endif
.mpred_above = {
.buf_size = 0x8000,
},
#ifdef MV_USE_FIXED_BUF
.mpred_mv = {
/*4k2k , 0x100000 per buffer*/
.buf_size = CO_MV_BUF_SIZE_8K * FRAME_BUFFERS,
},
#endif
.rpm = {
.buf_size = RPM_BUF_SIZE,
},
.lmem = {
.buf_size = 0x400 * 2,
}
}
};
#define IS_8K_SIZE(w, h) (((w) * (h)) > MAX_SIZE_4K)
#define IS_4K_SIZE(w, h) (((w) * (h)) > (1920*1088))
#ifndef MV_USE_FIXED_BUF
static uint32_t get_mv_buf_size(struct AVS2Decoder_s *dec, int width, int height) {
struct avs2_decoder *avs2_dec = &dec->avs2_dec;
uint32_t size;
if (mv_buf_dynamic_alloc == 1) {
int mv_mem_unit =
avs2_dec->lcu_size_log2 == 6 ? 0x200 : avs2_dec->lcu_size_log2 ==
5 ? 0x80 : 0x20;
int extended_pic_width = (width + avs2_dec->lcu_size -1)
& (~(avs2_dec->lcu_size - 1));
int extended_pic_height = (height + avs2_dec->lcu_size -1)
& (~(avs2_dec->lcu_size - 1));
int lcu_x_num = extended_pic_width / avs2_dec->lcu_size;
int lcu_y_num = extended_pic_height / avs2_dec->lcu_size;
int new_size = lcu_x_num * lcu_y_num * mv_mem_unit;
size = (new_size + 0xffff) & (~0xffff);
} else {
if (IS_8K_SIZE(width, height))
size = CO_MV_BUF_SIZE_8K;
else if (IS_4K_SIZE(width, height))
size = CO_MV_BUF_SIZE_4K;
else
size = CO_MV_BUF_SIZE_1080P;
}
return size;
}
#endif
/*Losless compression body buffer size 4K per 64x32 (jt)*/
static int compute_losless_comp_body_size(struct AVS2Decoder_s *dec,
int width, int height,
uint8_t is_bit_depth_10)
{
int width_x64;
int height_x32;
int bsize;
width_x64 = width + 63;
width_x64 >>= 6;
height_x32 = height + 31;
height_x32 >>= 5;
#ifdef AVS2_10B_MMU
bsize = (is_bit_depth_10 ? 4096 : 3200)
* width_x64 * height_x32;
#else
bsize = (is_bit_depth_10 ? 4096 : 3072)
* width_x64 * height_x32;
#endif
avs2_print(dec, AVS2_DBG_BUFMGR_MORE,
"%s(%d,%d,%d)=>%d\n",
__func__, width, height,
is_bit_depth_10, bsize);
return bsize;
}
/* Losless compression header buffer size 32bytes per 128x64 (jt)*/
static int compute_losless_comp_header_size(struct AVS2Decoder_s *dec,
int width, int height)
{
int width_x128;
int height_x64;
int hsize;
width_x128 = width + 127;
width_x128 >>= 7;
height_x64 = height + 63;
height_x64 >>= 6;
hsize = 32 * width_x128 * height_x64;
avs2_print(dec, AVS2_DBG_BUFMGR_MORE,
"%s(%d,%d)=>%d\n",
__func__, width, height,
hsize);
return hsize;
}
static void init_buff_spec(struct AVS2Decoder_s *dec,
struct BuffInfo_s *buf_spec)
{
void *mem_start_virt;
buf_spec->ipp.buf_start = buf_spec->start_adr;
buf_spec->sao_abv.buf_start =
buf_spec->ipp.buf_start + buf_spec->ipp.buf_size;
buf_spec->sao_vb.buf_start =
buf_spec->sao_abv.buf_start + buf_spec->sao_abv.buf_size;
buf_spec->short_term_rps.buf_start =
buf_spec->sao_vb.buf_start + buf_spec->sao_vb.buf_size;
buf_spec->rcs.buf_start =
buf_spec->short_term_rps.buf_start +
buf_spec->short_term_rps.buf_size;
buf_spec->sps.buf_start =
buf_spec->rcs.buf_start + buf_spec->rcs.buf_size;
buf_spec->pps.buf_start =
buf_spec->sps.buf_start + buf_spec->sps.buf_size;
buf_spec->sao_up.buf_start =
buf_spec->pps.buf_start + buf_spec->pps.buf_size;
buf_spec->swap_buf.buf_start =
buf_spec->sao_up.buf_start + buf_spec->sao_up.buf_size;
buf_spec->swap_buf2.buf_start =
buf_spec->swap_buf.buf_start + buf_spec->swap_buf.buf_size;
buf_spec->scalelut.buf_start =
buf_spec->swap_buf2.buf_start + buf_spec->swap_buf2.buf_size;
buf_spec->dblk_para.buf_start =
buf_spec->scalelut.buf_start + buf_spec->scalelut.buf_size;
buf_spec->dblk_data.buf_start =
buf_spec->dblk_para.buf_start + buf_spec->dblk_para.buf_size;
buf_spec->dblk_data2.buf_start =
buf_spec->dblk_data.buf_start + buf_spec->dblk_data.buf_size;
#ifdef AVS2_10B_MMU
buf_spec->mmu_vbh.buf_start =
buf_spec->dblk_data2.buf_start + buf_spec->dblk_data2.buf_size;
buf_spec->mpred_above.buf_start =
buf_spec->mmu_vbh.buf_start + buf_spec->mmu_vbh.buf_size;
#else
buf_spec->mpred_above.buf_start =
buf_spec->dblk_data2.buf_start + buf_spec->dblk_data2.buf_size;
#endif
#ifdef MV_USE_FIXED_BUF
buf_spec->mpred_mv.buf_start =
buf_spec->mpred_above.buf_start +
buf_spec->mpred_above.buf_size;
buf_spec->rpm.buf_start =
buf_spec->mpred_mv.buf_start +
buf_spec->mpred_mv.buf_size;
#else
buf_spec->rpm.buf_start =
buf_spec->mpred_above.buf_start +
buf_spec->mpred_above.buf_size;
#endif
buf_spec->lmem.buf_start =
buf_spec->rpm.buf_start +
buf_spec->rpm.buf_size;
buf_spec->end_adr =
buf_spec->lmem.buf_start +
buf_spec->lmem.buf_size;
if (dec) {
mem_start_virt =
codec_mm_phys_to_virt(buf_spec->dblk_para.buf_start);
if (mem_start_virt) {
memset(mem_start_virt, 0, buf_spec->dblk_para.buf_size);
codec_mm_dma_flush(mem_start_virt,
buf_spec->dblk_para.buf_size,
DMA_TO_DEVICE);
} else {
/*not virt for tvp playing,
may need clear on ucode.*/
pr_err("mem_start_virt failed\n");
}
if (debug) {
pr_info("%s workspace (%x %x) size = %x\n", __func__,
buf_spec->start_adr, buf_spec->end_adr,
buf_spec->end_adr - buf_spec->start_adr);
}
if (debug) {
pr_info("ipp.buf_start :%x\n",
buf_spec->ipp.buf_start);
pr_info("sao_abv.buf_start :%x\n",
buf_spec->sao_abv.buf_start);
pr_info("sao_vb.buf_start :%x\n",
buf_spec->sao_vb.buf_start);
pr_info("short_term_rps.buf_start :%x\n",
buf_spec->short_term_rps.buf_start);
pr_info("rcs.buf_start :%x\n",
buf_spec->rcs.buf_start);
pr_info("sps.buf_start :%x\n",
buf_spec->sps.buf_start);
pr_info("pps.buf_start :%x\n",
buf_spec->pps.buf_start);
pr_info("sao_up.buf_start :%x\n",
buf_spec->sao_up.buf_start);
pr_info("swap_buf.buf_start :%x\n",
buf_spec->swap_buf.buf_start);
pr_info("swap_buf2.buf_start :%x\n",
buf_spec->swap_buf2.buf_start);
pr_info("scalelut.buf_start :%x\n",
buf_spec->scalelut.buf_start);
pr_info("dblk_para.buf_start :%x\n",
buf_spec->dblk_para.buf_start);
pr_info("dblk_data.buf_start :%x\n",
buf_spec->dblk_data.buf_start);
pr_info("dblk_data2.buf_start :%x\n",
buf_spec->dblk_data2.buf_start);
#ifdef AVS2_10B_MMU
pr_info("mmu_vbh.buf_start :%x\n",
buf_spec->mmu_vbh.buf_start);
#endif
pr_info("mpred_above.buf_start :%x\n",
buf_spec->mpred_above.buf_start);
#ifdef MV_USE_FIXED_BUF
pr_info("mpred_mv.buf_start :%x\n",
buf_spec->mpred_mv.buf_start);
#endif
if ((debug & AVS2_DBG_SEND_PARAM_WITH_REG) == 0) {
pr_info("rpm.buf_start :%x\n",
buf_spec->rpm.buf_start);
}
}
}
}
static void uninit_mmu_buffers(struct AVS2Decoder_s *dec)
{
#if 0
/*ndef MV_USE_FIXED_BUF*/
dealloc_mv_bufs(dec);
#endif
decoder_mmu_box_free(dec->mmu_box);
dec->mmu_box = NULL;
if (dec->bmmu_box)
decoder_bmmu_box_free(dec->bmmu_box);
dec->bmmu_box = NULL;
}
#ifndef AVS2_10B_MMU
static void init_buf_list(struct AVS2Decoder_s *dec)
{
int i;
int buf_size;
int mc_buffer_end = dec->mc_buf->buf_start + dec->mc_buf->buf_size;
dec->used_buf_num = max_buf_num;
if (dec->used_buf_num > MAX_BUF_NUM)
dec->used_buf_num = MAX_BUF_NUM;
if (buf_alloc_size > 0) {
buf_size = buf_alloc_size;
avs2_print(dec, AVS2_DBG_BUFMGR,
"[Buffer Management] init_buf_list:\n");
} else {
int pic_width = dec->init_pic_w;
int pic_height = dec->init_pic_h;
/*SUPPORT_10BIT*/
int losless_comp_header_size = compute_losless_comp_header_size
(dec, pic_width, pic_height);
int losless_comp_body_size = compute_losless_comp_body_size
(dec, pic_width, pic_height, buf_alloc_depth == 10);
int mc_buffer_size = losless_comp_header_size
+ losless_comp_body_size;
int mc_buffer_size_h = (mc_buffer_size + 0xffff)>>16;
int dw_mode = get_double_write_mode_init(dec);
if (dw_mode) {
int pic_width_dw = pic_width /
get_double_write_ratio(dec, dw_mode);
int pic_height_dw = pic_height /
get_double_write_ratio(dec, dw_mode);
int lcu_size = 64; /*fixed 64*/
int pic_width_64 = (pic_width_dw + 63) & (~0x3f);
int pic_height_32 = (pic_height_dw + 31) & (~0x1f);
int pic_width_lcu =
(pic_width_64 % lcu_size) ? pic_width_64 / lcu_size
+ 1 : pic_width_64 / lcu_size;
int pic_height_lcu =
(pic_height_32 % lcu_size) ? pic_height_32 / lcu_size
+ 1 : pic_height_32 / lcu_size;
int lcu_total = pic_width_lcu * pic_height_lcu;
int mc_buffer_size_u_v = lcu_total * lcu_size * lcu_size / 2;
int mc_buffer_size_u_v_h = (mc_buffer_size_u_v + 0xffff) >> 16;
/*64k alignment*/
buf_size = ((mc_buffer_size_u_v_h << 16) * 3);
} else
buf_size = 0;
if (mc_buffer_size & 0xffff) { /*64k alignment*/
mc_buffer_size_h += 1;
}
if ((dw_mode & 0x10) == 0)
buf_size += (mc_buffer_size_h << 16);
avs2_print(dec, AVS2_DBG_BUFMGR,
"init_buf_list num %d (width %d height %d):\n",
dec->used_buf_num, pic_width, pic_height);
}
for (i = 0; i < dec->used_buf_num; i++) {
if (((i + 1) * buf_size) > dec->mc_buf->buf_size)
dec->use_cma_flag = 1;
#ifndef AVS2_10B_MMU
dec->m_BUF[i].alloc_flag = 0;
dec->m_BUF[i].index = i;
dec->use_cma_flag = 1;
if (dec->use_cma_flag) {
dec->m_BUF[i].cma_page_count =
PAGE_ALIGN(buf_size) / PAGE_SIZE;
if (decoder_bmmu_box_alloc_buf_phy(dec->bmmu_box,
VF_BUFFER_IDX(i), buf_size, DRIVER_NAME,
&dec->m_BUF[i].alloc_addr) < 0) {
dec->m_BUF[i].cma_page_count = 0;
if (i <= 5) {
dec->fatal_error |=
DECODER_FATAL_ERROR_NO_MEM;
}
break;
}
dec->m_BUF[i].start_adr = dec->m_BUF[i].alloc_addr;
} else {
dec->m_BUF[i].cma_page_count = 0;
dec->m_BUF[i].alloc_addr = 0;
dec->m_BUF[i].start_adr =
dec->mc_buf->buf_start + i * buf_size;
}
dec->m_BUF[i].size = buf_size;
dec->m_BUF[i].free_start_adr = dec->m_BUF[i].start_adr;
if (((dec->m_BUF[i].start_adr + buf_size) > mc_buffer_end)
&& (dec->m_BUF[i].alloc_addr == 0)) {
if (debug) {
avs2_print(dec, 0,
"Max mc buffer or mpred_mv buffer is used\n");
}
break;
}
avs2_print(dec, AVS2_DBG_BUFMGR,
"Buffer %d: start_adr %p size %x\n", i,
(void *)dec->m_BUF[i].start_adr,
dec->m_BUF[i].size);
#endif
}
dec->buf_num = i;
}
#endif
static int config_pic(struct AVS2Decoder_s *dec,
struct avs2_frame_s *pic, int32_t lcu_size_log2)
{
int ret = -1;
int i;
int pic_width = dec->init_pic_w;
int pic_height = dec->init_pic_h;
/*struct avs2_decoder *avs2_dec = &dec->avs2_dec;
int32_t lcu_size_log2 = avs2_dec->lcu_size_log2;*/
int32_t lcu_size = 1 << lcu_size_log2;
int pic_width_64 = (pic_width + 63) & (~0x3f);
int pic_height_32 = (pic_height + 31) & (~0x1f);
int pic_width_lcu = (pic_width_64 % lcu_size) ?
pic_width_64 / lcu_size + 1
: pic_width_64 / lcu_size;
int pic_height_lcu = (pic_height_32 % lcu_size) ?
pic_height_32 / lcu_size + 1
: pic_height_32 / lcu_size;
int lcu_total = pic_width_lcu * pic_height_lcu;
#if 0
int32_t MV_MEM_UNIT =
(lcu_size_log2 == 6) ? 0x200 :
((lcu_size_log2 == 5) ? 0x80 : 0x20);
#endif
#ifdef MV_USE_FIXED_BUF
u32 mpred_mv_end = dec->work_space_buf->mpred_mv.buf_start +
dec->work_space_buf->mpred_mv.buf_size;
#endif
u32 y_adr = 0;
int buf_size = 0;
int losless_comp_header_size =
compute_losless_comp_header_size(
dec, pic_width, pic_height);
int losless_comp_body_size = compute_losless_comp_body_size(
dec, pic_width,
pic_height, buf_alloc_depth == 10);
int mc_buffer_size = losless_comp_header_size + losless_comp_body_size;
int mc_buffer_size_h = (mc_buffer_size + 0xffff) >> 16;
int mc_buffer_size_u_v = 0;
int mc_buffer_size_u_v_h = 0;
int dw_mode = get_double_write_mode_init(dec);
if (dw_mode) {
int pic_width_dw = pic_width /
get_double_write_ratio(dec, dw_mode);
int pic_height_dw = pic_height /
get_double_write_ratio(dec, dw_mode);
int pic_width_64_dw = (pic_width_dw + 63) & (~0x3f);
int pic_height_32_dw = (pic_height_dw + 31) & (~0x1f);
int pic_width_lcu_dw = (pic_width_64_dw % lcu_size) ?
pic_width_64_dw / lcu_size + 1
: pic_width_64_dw / lcu_size;
int pic_height_lcu_dw = (pic_height_32_dw % lcu_size) ?
pic_height_32_dw / lcu_size + 1
: pic_height_32_dw / lcu_size;
int lcu_total_dw = pic_width_lcu_dw * pic_height_lcu_dw;
mc_buffer_size_u_v = lcu_total_dw * lcu_size * lcu_size / 2;
mc_buffer_size_u_v_h = (mc_buffer_size_u_v + 0xffff) >> 16;
/*64k alignment*/
buf_size = ((mc_buffer_size_u_v_h << 16) * 3);
buf_size = ((buf_size + 0xffff) >> 16) << 16;
}
if (mc_buffer_size & 0xffff) /*64k alignment*/
mc_buffer_size_h += 1;
#ifndef AVS2_10B_MMU
if ((dw_mode & 0x10) == 0)
buf_size += (mc_buffer_size_h << 16);
#endif
#ifdef AVS2_10B_MMU
#ifndef DYNAMIC_ALLOC_HEAD
pic->header_adr = decoder_bmmu_box_get_phy_addr(
dec->bmmu_box, HEADER_BUFFER_IDX(pic->index));
avs2_print(dec, AVS2_DBG_BUFMGR_MORE,
"buf_size %d, MMU header_adr %d: %ld\n",
buf_size, pic->index, pic->header_adr);
#endif
#endif
i = pic->index;
#ifdef MV_USE_FIXED_BUF
#ifdef G12A_BRINGUP_DEBUG
if (1) {
#else
if ((dec->work_space_buf->mpred_mv.buf_start +
(((i + 1) * lcu_total) * MV_MEM_UNIT))
<= mpred_mv_end
) {
#endif
#endif
#ifndef AVS2_10B_MMU
if (debug) {
pr_err("start %x .size=%d\n",
dec->mc_buf_spec.buf_start + i * buf_size,
buf_size);
}
#endif
#ifndef AVS2_10B_MMU
for (i = 0; i < dec->buf_num; i++) {
y_adr = ((dec->m_BUF[i].free_start_adr
+ 0xffff) >> 16) << 16;
/*64k alignment*/
if ((y_adr+buf_size) <= (dec->m_BUF[i].start_adr+
dec->m_BUF[i].size)) {
dec->m_BUF[i].free_start_adr =
y_adr + buf_size;
break;
}
}
if (i < dec->buf_num)
#else
/*if ((dec->mc_buf->buf_start + (i + 1) * buf_size) <
dec->mc_buf->buf_end)
y_adr = dec->mc_buf->buf_start + i * buf_size;
else {*/
if (buf_size > 0 && pic->cma_alloc_addr == 0) {
ret = decoder_bmmu_box_alloc_buf_phy(dec->bmmu_box,
VF_BUFFER_IDX(i),
buf_size, DRIVER_NAME,
&pic->cma_alloc_addr);
if (ret < 0) {
avs2_print(dec, 0,
"decoder_bmmu_box_alloc_buf_phy idx %d size %d fail\n",
VF_BUFFER_IDX(i),
buf_size
);
return ret;
}
if (pic->cma_alloc_addr)
y_adr = pic->cma_alloc_addr;
else {
avs2_print(dec, 0,
"decoder_bmmu_box_alloc_buf_phy idx %d size %d return null\n",
VF_BUFFER_IDX(i),
buf_size
);
return -1;
}
}
#endif
{
/*ensure get_pic_by_POC()
not get the buffer not decoded*/
pic->BUF_index = i;
pic->lcu_total = lcu_total;
pic->comp_body_size = losless_comp_body_size;
pic->buf_size = buf_size;
#ifndef AVS2_10B_MMU
pic->mc_y_adr = y_adr;
#endif
pic->mc_canvas_y = pic->index;
pic->mc_canvas_u_v = pic->index;
#ifndef AVS2_10B_MMU
if (dw_mode & 0x10) {
pic->mc_u_v_adr = y_adr +
((mc_buffer_size_u_v_h << 16) << 1);
pic->mc_canvas_y =
(pic->index << 1);
pic->mc_canvas_u_v =
(pic->index << 1) + 1;
pic->dw_y_adr = y_adr;
pic->dw_u_v_adr = pic->mc_u_v_adr;
} else
#endif
if (dw_mode) {
pic->dw_y_adr = y_adr
#ifndef AVS2_10B_MMU
+ (mc_buffer_size_h << 16)
#endif
;
pic->dw_u_v_adr = pic->dw_y_adr +
((mc_buffer_size_u_v_h << 16) << 1);
#ifdef AVS2_10B_MMU
pic->mc_y_adr = pic->dw_y_adr;
pic->mc_u_v_adr = pic->dw_u_v_adr;
#endif
}
#ifdef MV_USE_FIXED_BUF
#ifdef G12A_BRINGUP_DEBUG
if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) {
pic->mpred_mv_wr_start_addr =
dec->work_space_buf->mpred_mv.buf_start +
(pic->index * 0x120000 * 4);
} else {
pic->mpred_mv_wr_start_addr =
dec->work_space_buf->mpred_mv.buf_start +
(pic->index * 0x120000);
}
#else
pic->mpred_mv_wr_start_addr =
dec->work_space_buf->mpred_mv.buf_start +
((pic->index * lcu_total)
* MV_MEM_UNIT);
#endif
#endif
if (debug) {
avs2_print(dec, AVS2_DBG_BUFMGR,
"%s index %d BUF_index %d mc_y_adr %x ",
__func__, pic->index,
pic->BUF_index,
pic->mc_y_adr);
avs2_print_cont(dec, AVS2_DBG_BUFMGR,
"comp_body_size %x comp_buf_size %x ",
pic->comp_body_size,
pic->buf_size);
avs2_print_cont(dec, AVS2_DBG_BUFMGR,
"mpred_mv_wr_start_adr %d\n",
pic->mpred_mv_wr_start_addr);
avs2_print_cont(dec, AVS2_DBG_BUFMGR,
"dw_y_adr %d, pic->dw_u_v_adr =%d\n",
pic->dw_y_adr,
pic->dw_u_v_adr);
}
ret = 0;
}
#ifdef MV_USE_FIXED_BUF
} else {
avs2_print(dec, 0,
"mv buffer alloc fail %x > %x\n",
dec->work_space_buf->mpred_mv.buf_start +
(((i + 1) * lcu_total) * MV_MEM_UNIT),
mpred_mv_end);
}
#endif
return ret;
}
static void init_pic_list(struct AVS2Decoder_s *dec,
int32_t lcu_size_log2)
{
int i;
struct avs2_decoder *avs2_dec = &dec->avs2_dec;
struct avs2_frame_s *pic;
#ifdef AVS2_10B_MMU
unsigned long buf_addr1;
/*alloc AVS2 compress header first*/
if (decoder_bmmu_box_alloc_buf_phy
(dec->bmmu_box,
HEADER_BUFFER_IDX(-1), get_compress_header_size(dec),
DRIVER_HEADER_NAME,
&buf_addr1) < 0){
avs2_print(dec, 0,
"%s malloc compress header failed %d\n",
DRIVER_HEADER_NAME, -1);
dec->fatal_error |= DECODER_FATAL_ERROR_NO_MEM;
return;
}
#ifndef DYNAMIC_ALLOC_HEAD
for (i = 0; i < dec->used_buf_num; i++) {
unsigned long buf_addr;
if (decoder_bmmu_box_alloc_buf_phy
(dec->bmmu_box,
HEADER_BUFFER_IDX(i), get_compress_header_size(dec),
DRIVER_HEADER_NAME,
&buf_addr) < 0){
avs2_print(dec, 0,
"%s malloc compress header failed %d\n",
DRIVER_HEADER_NAME, i);
dec->fatal_error |= DECODER_FATAL_ERROR_NO_MEM;
return;
}
}
#endif
#endif
dec->frame_height = avs2_dec->img.height;
dec->frame_width = avs2_dec->img.width;
for (i = 0; i < dec->used_buf_num; i++) {
if (i == (dec->used_buf_num - 1))
pic = avs2_dec->m_bg;
else
pic = avs2_dec->fref[i];
pic->index = i;
pic->BUF_index = -1;
pic->mv_buf_index = -1;
if (config_pic(dec, pic, lcu_size_log2) < 0) {
if (debug)
avs2_print(dec, 0,
"Config_pic %d fail\n",
pic->index);
pic->index = -1;
break;
}
pic->pic_w = avs2_dec->img.width;
pic->pic_h = avs2_dec->img.height;
}
for (; i < dec->used_buf_num; i++) {
if (i == (dec->used_buf_num - 1))
pic = avs2_dec->m_bg;
else
pic = avs2_dec->fref[i];
pic->index = -1;
pic->BUF_index = -1;
pic->mv_buf_index = -1;
}
avs2_print(dec, AVS2_DBG_BUFMGR,
"%s ok, used_buf_num = %d\n",
__func__, dec->used_buf_num);
dec->pic_list_init_flag = 1;
}
static void init_pic_list_hw(struct AVS2Decoder_s *dec)
{
int i;
struct avs2_decoder *avs2_dec = &dec->avs2_dec;
struct avs2_frame_s *pic;
/*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 0x0);*/
#if 0
WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR,
(0x1 << 1) | (0x1 << 2));
#ifdef DUAL_CORE_64
WRITE_VREG(HEVC2_HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR,
(0x1 << 1) | (0x1 << 2));
#endif
#endif
for (i = 0; i < dec->used_buf_num; i++) {
if (i == (dec->used_buf_num - 1))
pic = avs2_dec->m_bg;
else
pic = avs2_dec->fref[i];
if (pic->index < 0)
break;
#ifdef AVS2_10B_MMU
/*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR,
pic->header_adr
| (pic->mc_canvas_y << 8)|0x1);*/
WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR,
(0x1 << 1) | (pic->index << 8));
#ifdef DUAL_CORE_64
if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXLX2)
WRITE_VREG(HEVC2_MPP_ANC2AXI_TBL_CONF_ADDR,
(0x1 << 1) | (pic->index << 8));
else
WRITE_VREG(HEVC2_HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR,
(0x1 << 1) | (pic->index << 8));
#endif
WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, pic->header_adr >> 5);
#else
/*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR,
pic->mc_y_adr
| (pic->mc_canvas_y << 8) | 0x1);*/
WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, pic->mc_y_adr >> 5);
#endif
#ifndef LOSLESS_COMPRESS_MODE
/*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR,
pic->mc_u_v_adr
| (pic->mc_canvas_u_v << 8)| 0x1);*/
WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, pic->mc_u_v_adr >> 5);
#endif
#ifdef DUAL_CORE_64
#ifdef AVS2_10B_MMU
WRITE_VREG(HEVC2_HEVCD_MPP_ANC2AXI_TBL_DATA,
pic->header_adr >> 5);
#else
WRITE_VREG(HEVC2_HEVCD_MPP_ANC2AXI_TBL_DATA,
pic->mc_y_adr >> 5);
#endif
#ifndef LOSLESS_COMPRESS_MODE
WRITE_VREG(HEVC2_HEVCD_MPP_ANC2AXI_TBL_DATA,
pic->mc_u_v_adr >> 5);
#endif
/*DUAL_CORE_64*/
#endif
}
WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 0x1);
#ifdef DUAL_CORE_64
WRITE_VREG(HEVC2_HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR,
0x1);
#endif
/*Zero out canvas registers in IPP -- avoid simulation X*/
WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
(0 << 8) | (0 << 1) | 1);
for (i = 0; i < 32; i++) {
WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, 0);
#ifdef DUAL_CORE_64
WRITE_VREG(HEVC2_HEVCD_MPP_ANC_CANVAS_DATA_ADDR, 0);
#endif
}
}
static void dump_pic_list(struct AVS2Decoder_s *dec)
{
int ii;
struct avs2_decoder *avs2_dec = &dec->avs2_dec;
for (ii = 0; ii < avs2_dec->ref_maxbuffer; ii++) {
avs2_print(dec, 0,
"fref[%d]: index %d decode_id %d mvbuf %d imgcoi_ref %d imgtr_fwRefDistance %d refered %d, pre %d is_out %d, bg %d, vf_ref %d error %d lcu %d ref_pos(%d,%d,%d,%d,%d,%d,%d)\n",
ii, avs2_dec->fref[ii]->index,
avs2_dec->fref[ii]->decode_idx,
avs2_dec->fref[ii]->mv_buf_index,
avs2_dec->fref[ii]->imgcoi_ref,
avs2_dec->fref[ii]->imgtr_fwRefDistance,
avs2_dec->fref[ii]->refered_by_others,
avs2_dec->fref[ii]->to_prepare_disp,
avs2_dec->fref[ii]->is_output,
avs2_dec->fref[ii]->bg_flag,
avs2_dec->fref[ii]->vf_ref,
avs2_dec->fref[ii]->error_mark,
avs2_dec->fref[ii]->decoded_lcu,
avs2_dec->fref[ii]->ref_poc[0],
avs2_dec->fref[ii]->ref_poc[1],
avs2_dec->fref[ii]->ref_poc[2],
avs2_dec->fref[ii]->ref_poc[3],
avs2_dec->fref[ii]->ref_poc[4],
avs2_dec->fref[ii]->ref_poc[5],
avs2_dec->fref[ii]->ref_poc[6]
);
}
return;
}
static int config_mc_buffer(struct AVS2Decoder_s *dec)
{
int32_t i;
struct avs2_decoder *avs2_dec = &dec->avs2_dec;
struct avs2_frame_s *pic;
struct avs2_frame_s *cur_pic = avs2_dec->hc.cur_pic;
/*if (avs2_dec->img.type == I_IMG)
return 0;
*/
avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
"Entered config_mc_buffer....\n");
if (avs2_dec->f_bg != NULL) {
avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
"config_mc_buffer for background (canvas_y %d, canvas_u_v %d)\n",
avs2_dec->f_bg->mc_canvas_y, avs2_dec->f_bg->mc_canvas_u_v);
/*WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
(7 << 8) | (0<<1) | 1); L0:BG */
WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
(15 << 8) | (0<<1) | 1); /* L0:BG*/
WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR,
(avs2_dec->f_bg->mc_canvas_u_v << 16) |
(avs2_dec->f_bg->mc_canvas_u_v << 8) |
avs2_dec->f_bg->mc_canvas_y);
/*WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
(23 << 8) | (0<<1) | 1); L1:BG*/
WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
(31 << 8) | (0<<1) | 1); /* L1:BG*/
WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR,
(avs2_dec->f_bg->mc_canvas_u_v << 16) |
(avs2_dec->f_bg->mc_canvas_u_v << 8) |
avs2_dec->f_bg->mc_canvas_y);
}
if (avs2_dec->img.type == I_IMG)
return 0;
if (avs2_dec->img.type == P_IMG) {
avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
"config_mc_buffer for P_IMG, img type %d\n",
avs2_dec->img.type);
/*refer to prepare_RefInfo()*/
WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
(0 << 8) | (0<<1) | 1);
for (i = 0; i < avs2_dec->img.num_of_references; i++) {
pic = avs2_dec->fref[i];
WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR,
(pic->mc_canvas_u_v << 16) |
(pic->mc_canvas_u_v << 8) |
pic->mc_canvas_y);
if (pic->error_mark)
cur_pic->error_mark = 1;
avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
"refid %x mc_canvas_u_v %x mc_canvas_y %x error_mark %x\n",
i, pic->mc_canvas_u_v, pic->mc_canvas_y,
pic->error_mark);
}
} else if (avs2_dec->img.type == F_IMG) {
avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
"config_mc_buffer for F_IMG, img type %d\n",
avs2_dec->img.type);
/*refer to prepare_RefInfo()*/
WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
(0 << 8) | (0<<1) | 1);
for (i = 0; i < avs2_dec->img.num_of_references; i++) {
pic = avs2_dec->fref[i];
WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR,
(pic->mc_canvas_u_v << 16) |
(pic->mc_canvas_u_v << 8) |
pic->mc_canvas_y);
if (pic->error_mark)
cur_pic->error_mark = 1;
avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
"refid %x mc_canvas_u_v %x mc_canvas_y %x error_mark %x\n",
i, pic->mc_canvas_u_v, pic->mc_canvas_y,
pic->error_mark);
}
WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
(16 << 8) | (0<<1) | 1);
for (i = 0; i < avs2_dec->img.num_of_references; i++) {
pic = avs2_dec->fref[i];
WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR,
(pic->mc_canvas_u_v << 16) |
(pic->mc_canvas_u_v << 8) |
pic->mc_canvas_y);
avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
"refid %x mc_canvas_u_v %x mc_canvas_y %x\n",
i, pic->mc_canvas_u_v, pic->mc_canvas_y);
}
} else {
avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
"config_mc_buffer for B_IMG\n");
/*refer to prepare_RefInfo()*/
pic = avs2_dec->fref[1];
WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
(0 << 8) | (0<<1) | 1);
WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR,
(pic->mc_canvas_u_v << 16) |
(pic->mc_canvas_u_v << 8) |
pic->mc_canvas_y);
if (pic->error_mark)
cur_pic->error_mark = 1;
avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
"refid %x mc_canvas_u_v %x mc_canvas_y %x error_mark %x\n",
1, pic->mc_canvas_u_v, pic->mc_canvas_y,
pic->error_mark);
pic = avs2_dec->fref[0];
WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
(16 << 8) | (0<<1) | 1);
WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR,
(pic->mc_canvas_u_v<<16) |
(pic->mc_canvas_u_v<<8) |
pic->mc_canvas_y);
if (pic->error_mark)
cur_pic->error_mark = 1;
avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
"refid %x mc_canvas_u_v %x mc_canvas_y %x error_mark %x\n",
0, pic->mc_canvas_u_v, pic->mc_canvas_y,
pic->error_mark);
}
return 0;
}
#if 0
static void mcrcc_get_hitrate(void)
{
u32 tmp;
u32 raw_mcr_cnt;
u32 hit_mcr_cnt;
u32 byp_mcr_cnt_nchoutwin;
u32 byp_mcr_cnt_nchcanv;
int hitrate;
if (debug & AVS2_DBG_CACHE)
pr_info("[cache_util.c] Entered mcrcc_get_hitrate...\n");
WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x0<<1));
raw_mcr_cnt = READ_VREG(HEVCD_MCRCC_PERFMON_DATA);
WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x1<<1));
hit_mcr_cnt = READ_VREG(HEVCD_MCRCC_PERFMON_DATA);
WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x2<<1));
byp_mcr_cnt_nchoutwin = READ_VREG(HEVCD_MCRCC_PERFMON_DATA);
WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x3<<1));
byp_mcr_cnt_nchcanv = READ_VREG(HEVCD_MCRCC_PERFMON_DATA);
if (debug & AVS2_DBG_CACHE) {
pr_info("raw_mcr_cnt_total: %d\n",raw_mcr_cnt);
pr_info("hit_mcr_cnt_total: %d\n",hit_mcr_cnt);
pr_info("byp_mcr_cnt_nchoutwin_total: %d\n",byp_mcr_cnt_nchoutwin);
pr_info("byp_mcr_cnt_nchcanv_total: %d\n",byp_mcr_cnt_nchcanv);
}
WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x4<<1));
tmp = READ_VREG(HEVCD_MCRCC_PERFMON_DATA);
if (debug & AVS2_DBG_CACHE)
pr_info("miss_mcr_0_cnt_total: %d\n", tmp);
WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x5<<1));
tmp = READ_VREG(HEVCD_MCRCC_PERFMON_DATA);
if (debug & AVS2_DBG_CACHE)
pr_info("miss_mcr_1_cnt_total: %d\n", tmp);
WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x6<<1));
tmp = READ_VREG(HEVCD_MCRCC_PERFMON_DATA);
if (debug & AVS2_DBG_CACHE)
pr_info("hit_mcr_0_cnt_total: %d\n",tmp);
WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x7<<1));
tmp= READ_VREG(HEVCD_MCRCC_PERFMON_DATA);
if (debug & AVS2_DBG_CACHE)
pr_info("hit_mcr_1_cnt_total: %d\n",tmp);
if (raw_mcr_cnt != 0) {
hitrate = (hit_mcr_cnt / raw_mcr_cnt) * 100;
if (debug & AVS2_DBG_CACHE)
pr_info("MCRCC_HIT_RATE : %d\n", hitrate);
hitrate = ((byp_mcr_cnt_nchoutwin + byp_mcr_cnt_nchcanv)
/raw_mcr_cnt) * 100;
if (debug & AVS2_DBG_CACHE)
pr_info("MCRCC_BYP_RATE : %d\n", hitrate);
} else if (debug & AVS2_DBG_CACHE) {
pr_info("MCRCC_HIT_RATE : na\n");
pr_info("MCRCC_BYP_RATE : na\n");
}
return;
}
static void decomp_get_hitrate(void)
{
u32 raw_mcr_cnt;
u32 hit_mcr_cnt;
int hitrate;
if (debug & AVS2_DBG_CACHE)
pr_info("[cache_util.c] Entered decomp_get_hitrate...\n");
WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x0<<1));
raw_mcr_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA);
WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x1<<1));
hit_mcr_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA);
if (debug & AVS2_DBG_CACHE) {
pr_info("hcache_raw_cnt_total: %d\n",raw_mcr_cnt);
pr_info("hcache_hit_cnt_total: %d\n",hit_mcr_cnt);
}
if (raw_mcr_cnt != 0) {
hitrate = (hit_mcr_cnt / raw_mcr_cnt) * 100;
if (debug & AVS2_DBG_CACHE)
pr_info("DECOMP_HCACHE_HIT_RATE : %d\n", hitrate);
} else {
if (debug & AVS2_DBG_CACHE)
pr_info("DECOMP_HCACHE_HIT_RATE : na\n");
}
WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x2<<1));
raw_mcr_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA);
WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x3<<1));
hit_mcr_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA);
if (debug & AVS2_DBG_CACHE) {
pr_info("dcache_raw_cnt_total: %d\n", raw_mcr_cnt);
pr_info("dcache_hit_cnt_total: %d\n", hit_mcr_cnt);
}
if (raw_mcr_cnt != 0) {
hitrate = (hit_mcr_cnt / raw_mcr_cnt) * 100;
if (debug & AVS2_DBG_CACHE)
pr_info("DECOMP_DCACHE_HIT_RATE : %d\n", hitrate);
} else if (debug & AVS2_DBG_CACHE) {
pr_info("DECOMP_DCACHE_HIT_RATE : na\n");
}
return;
}
static void decomp_get_comprate(void)
{
u32 raw_ucomp_cnt;
u32 fast_comp_cnt;
u32 slow_comp_cnt;
int comprate;
if (debug & AVS2_DBG_CACHE)
pr_info("[cache_util.c] Entered decomp_get_comprate...\n");
WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x4<<1));
fast_comp_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA);
WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x5<<1));
slow_comp_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA);
WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x6<<1));
raw_ucomp_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA);
if (debug & AVS2_DBG_CACHE) {
pr_info("decomp_fast_comp_total: %d\n", fast_comp_cnt);
pr_info("decomp_slow_comp_total: %d\n", slow_comp_cnt);
pr_info("decomp_raw_uncomp_total: %d\n", raw_ucomp_cnt);
}
if (raw_ucomp_cnt != 0) {
comprate = ((fast_comp_cnt + slow_comp_cnt)
/ raw_ucomp_cnt) * 100;
if (debug & AVS2_DBG_CACHE)
pr_info("DECOMP_COMP_RATIO : %d\n", comprate);
} else if (debug & AVS2_DBG_CACHE) {
pr_info("DECOMP_COMP_RATIO : na\n");
}
return;
}
#endif
static void config_mcrcc_axi_hw(struct AVS2Decoder_s *dec)
{
uint32_t rdata32;
uint32_t rdata32_2;
struct avs2_decoder *avs2_dec = &dec->avs2_dec;
WRITE_VREG(HEVCD_MCRCC_CTL1, 0x2); /* reset mcrcc*/
if (avs2_dec->img.type == I_IMG) { /* I-PIC*/
/* remove reset -- disables clock */
WRITE_VREG(HEVCD_MCRCC_CTL1, 0x0);
return;
}
/*
if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) {
mcrcc_get_hitrate();
decomp_get_hitrate();
decomp_get_comprate();
}
*/
if ((avs2_dec->img.type == B_IMG) ||
(avs2_dec->img.type == F_IMG)) { /*B-PIC or F_PIC*/
/*Programme canvas0 */
WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
(0 << 8) | (0 << 1) | 0);
rdata32 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR);
rdata32 = rdata32 & 0xffff;
rdata32 = rdata32 | (rdata32 << 16);
WRITE_VREG(HEVCD_MCRCC_CTL2, rdata32);
/*Programme canvas1 */
WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
(16 << 8) | (1 << 1) | 0);
rdata32_2 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR);
rdata32_2 = rdata32_2 & 0xffff;
rdata32_2 = rdata32_2 | (rdata32_2 << 16);
if (rdata32 == rdata32_2) {
rdata32_2 =
READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR);
rdata32_2 = rdata32_2 & 0xffff;
rdata32_2 = rdata32_2 | (rdata32_2 << 16);
}
WRITE_VREG(HEVCD_MCRCC_CTL3, rdata32_2);
} else { /* P-PIC */
WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
(0 << 8) | (1 << 1) | 0);
rdata32 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR);
rdata32 = rdata32 & 0xffff;
rdata32 = rdata32 | (rdata32 << 16);
WRITE_VREG(HEVCD_MCRCC_CTL2, rdata32);
/*Programme canvas1*/
rdata32 =
READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR);
rdata32 = rdata32 & 0xffff;
rdata32 = rdata32 | (rdata32 << 16);
WRITE_VREG(HEVCD_MCRCC_CTL3, rdata32);
}
/*enable mcrcc progressive-mode */
WRITE_VREG(HEVCD_MCRCC_CTL1, 0xff0);
return;
}
static void config_mpred_hw(struct AVS2Decoder_s *dec)
{
uint32_t data32;
struct avs2_decoder *avs2_dec = &dec->avs2_dec;
struct avs2_frame_s *cur_pic = avs2_dec->hc.cur_pic;
struct avs2_frame_s *col_pic = avs2_dec->fref[0];
int32_t mpred_mv_rd_start_addr;
int32_t mpred_curr_lcu_x;
int32_t mpred_curr_lcu_y;
int32_t mpred_mv_rd_end_addr;
int32_t above_en;
int32_t mv_wr_en;
int32_t mv_rd_en;
int32_t col_isIntra;
int mv_mem_unit;
if (avs2_dec->img.type != I_IMG) {
above_en = 1;
mv_wr_en = 1;
mv_rd_en = 1;
col_isIntra = 0;
} else {
above_en = 1;
mv_wr_en = 1;
mv_rd_en = 0;
col_isIntra = 0;
}
mpred_mv_rd_start_addr =
col_pic->mpred_mv_wr_start_addr;
data32 = READ_VREG(HEVC_MPRED_CURR_LCU);
mpred_curr_lcu_x = data32 & 0xffff;
mpred_curr_lcu_y = (data32 >> 16) & 0xffff;
mv_mem_unit = avs2_dec->lcu_size_log2 == 6 ?
0x200 : (avs2_dec->lcu_size_log2 == 5 ?
0x80 : 0x20);
mpred_mv_rd_end_addr =
mpred_mv_rd_start_addr +
((avs2_dec->lcu_x_num *
avs2_dec->lcu_y_num) * mv_mem_unit);
avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
"cur pic index %d col pic index %d\n",
cur_pic->index, col_pic->index);
WRITE_VREG(HEVC_MPRED_MV_WR_START_ADDR,
cur_pic->mpred_mv_wr_start_addr);
WRITE_VREG(HEVC_MPRED_MV_RD_START_ADDR,
col_pic->mpred_mv_wr_start_addr);
avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
"[MPRED CO_MV] write 0x%x read 0x%x\n",
cur_pic->mpred_mv_wr_start_addr,
col_pic->mpred_mv_wr_start_addr);
data32 =
((avs2_dec->bk_img_is_top_field) << 13) |
((avs2_dec->hd.background_picture_enable & 1) << 12) |
((avs2_dec->hd.curr_RPS.num_of_ref & 7) << 8) |
((avs2_dec->hd.b_pmvr_enabled & 1) << 6) |
((avs2_dec->img.is_top_field & 1) << 5) |
((avs2_dec->img.is_field_sequence & 1) << 4) |
((avs2_dec->img.typeb & 7) << 1) |
(avs2_dec->hd.background_reference_enable & 0x1);
avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
"HEVC_MPRED_CTRL9 <= 0x%x(num of ref %d)\n",
data32, avs2_dec->hd.curr_RPS.num_of_ref);
WRITE_VREG(HEVC_MPRED_CTRL9, data32);
avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
"%s: dis %d %d %d %d %d %d %d fref0_ref_poc %d %d %d %d %d %d %d\n",
__func__,
avs2_dec->fref[0]->imgtr_fwRefDistance,
avs2_dec->fref[1]->imgtr_fwRefDistance,
avs2_dec->fref[2]->imgtr_fwRefDistance,
avs2_dec->fref[3]->imgtr_fwRefDistance,
avs2_dec->fref[4]->imgtr_fwRefDistance,
avs2_dec->fref[5]->imgtr_fwRefDistance,
avs2_dec->fref[6]->imgtr_fwRefDistance,
avs2_dec->fref[0]->ref_poc[0],
avs2_dec->fref[0]->ref_poc[1],
avs2_dec->fref[0]->ref_poc[2],
avs2_dec->fref[0]->ref_poc[3],
avs2_dec->fref[0]->ref_poc[4],
avs2_dec->fref[0]->ref_poc[5],
avs2_dec->fref[0]->ref_poc[6]
);
avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
"pic_distance %d, imgtr_next_P %d\n",
avs2_dec->img.pic_distance, avs2_dec->img.imgtr_next_P);
WRITE_VREG(HEVC_MPRED_CUR_POC, avs2_dec->img.pic_distance);
WRITE_VREG(HEVC_MPRED_COL_POC, avs2_dec->img.imgtr_next_P);
/*below MPRED Ref_POC_xx_Lx registers
must follow Ref_POC_xx_L0 ->
Ref_POC_xx_L1 in pair write order!!!*/
WRITE_VREG(HEVC_MPRED_L0_REF00_POC,
avs2_dec->fref[0]->imgtr_fwRefDistance);
WRITE_VREG(HEVC_MPRED_L1_REF00_POC,
avs2_dec->fref[0]->ref_poc[0]);
WRITE_VREG(HEVC_MPRED_L0_REF01_POC,
avs2_dec->fref[1]->imgtr_fwRefDistance);
WRITE_VREG(HEVC_MPRED_L1_REF01_POC,
avs2_dec->fref[0]->ref_poc[1]);
WRITE_VREG(HEVC_MPRED_L0_REF02_POC,
avs2_dec->fref[2]->imgtr_fwRefDistance);
WRITE_VREG(HEVC_MPRED_L1_REF02_POC,
avs2_dec->fref[0]->ref_poc[2]);
WRITE_VREG(HEVC_MPRED_L0_REF03_POC,
avs2_dec->fref[3]->imgtr_fwRefDistance);
WRITE_VREG(HEVC_MPRED_L1_REF03_POC,
avs2_dec->fref[0]->ref_poc[3]);
WRITE_VREG(HEVC_MPRED_L0_REF04_POC,
avs2_dec->fref[4]->imgtr_fwRefDistance);
WRITE_VREG(HEVC_MPRED_L1_REF04_POC,
avs2_dec->fref[0]->ref_poc[4]);
WRITE_VREG(HEVC_MPRED_L0_REF05_POC,
avs2_dec->fref[5]->imgtr_fwRefDistance);
WRITE_VREG(HEVC_MPRED_L1_REF05_POC,
avs2_dec->fref[0]->ref_poc[5]);
WRITE_VREG(HEVC_MPRED_L0_REF06_POC,
avs2_dec->fref[6]->imgtr_fwRefDistance);
WRITE_VREG(HEVC_MPRED_L1_REF06_POC,
avs2_dec->fref[0]->ref_poc[6]);
WRITE_VREG(HEVC_MPRED_MV_RD_END_ADDR,
mpred_mv_rd_end_addr);
}
static void config_dblk_hw(struct AVS2Decoder_s *dec)
{
/*
* Picture level de-block parameter configuration here
*/
struct avs2_decoder *avs2_dec = &dec->avs2_dec;
union param_u *rpm_param = &avs2_dec->param;
uint32_t data32;
data32 = READ_VREG(HEVC_DBLK_CFG1);
data32 = (((data32 >> 20) & 0xfff) << 20) |
(((avs2_dec->input.sample_bit_depth == 10)
? 0xa : 0x0) << 16) | /*[16 +: 4]: {luma_bd[1:0],
chroma_bd[1:0]}*/
(((data32 >> 2) & 0x3fff) << 2) |
(((rpm_param->p.lcu_size == 6)
? 0 : (rpm_param->p.lcu_size == 5)
? 1 : 2) << 0);/*[ 0 +: 2]: lcu_size*/
WRITE_VREG(HEVC_DBLK_CFG1, data32);
data32 = (avs2_dec->img.height << 16) |
avs2_dec->img.width;
WRITE_VREG(HEVC_DBLK_CFG2, data32);
/*
[27 +: 1]: cross_slice_loopfilter_enable_flag
[26 +: 1]: loop_filter_disable
[25 +: 1]: useNSQT
[22 +: 3]: imgtype
[17 +: 5]: alpha_c_offset (-8~8)
[12 +: 5]: beta_offset (-8~8)
[ 6 +: 6]: chroma_quant_param_delta_u (-16~16)
[ 0 +: 6]: chroma_quant_param_delta_v (-16~16)
*/
data32 = ((avs2_dec->input.crossSliceLoopFilter
& 0x1) << 27) |
((rpm_param->p.loop_filter_disable & 0x1) << 26) |
((avs2_dec->input.useNSQT & 0x1) << 25) |
((avs2_dec->img.type & 0x7) << 22) |
((rpm_param->p.alpha_c_offset & 0x1f) << 17) |
((rpm_param->p.beta_offset & 0x1f) << 12) |
((rpm_param->p.chroma_quant_param_delta_cb & 0x3f) << 6) |
((rpm_param->p.chroma_quant_param_delta_cr & 0x3f) << 0);
WRITE_VREG(HEVC_DBLK_CFG9, data32);
avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
"[c] cfgDBLK: crossslice(%d),lfdisable(%d),bitDepth(%d),lcuSize(%d),NSQT(%d)\n",
avs2_dec->input.crossSliceLoopFilter,
rpm_param->p.loop_filter_disable,
avs2_dec->input.sample_bit_depth,
avs2_dec->lcu_size,
avs2_dec->input.useNSQT);
avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
"[c] cfgDBLK: alphaCOffset(%d),betaOffset(%d),quantDeltaCb(%d),quantDeltaCr(%d)\n",
rpm_param->p.alpha_c_offset,
rpm_param->p.beta_offset,
rpm_param->p.chroma_quant_param_delta_cb,
rpm_param->p.chroma_quant_param_delta_cr);
avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
"[c] cfgDBLK: .done.\n");
}
static void config_sao_hw(struct AVS2Decoder_s *dec)
{
uint32_t data32;
struct avs2_decoder *avs2_dec = &dec->avs2_dec;
struct avs2_frame_s *cur_pic = avs2_dec->hc.cur_pic;
int lcu_size = 64;
int mc_buffer_size_u_v =
cur_pic->lcu_total * lcu_size*lcu_size/2;
int mc_buffer_size_u_v_h =
(mc_buffer_size_u_v + 0xffff) >> 16;/*64k alignment*/
data32 = READ_VREG(HEVC_SAO_CTRL0);
data32 &= (~0xf);
data32 |= avs2_dec->lcu_size_log2;
avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
"%s, lcu_size_log2 = %d, config HEVC_SAO_CTRL0 0x%x\n",
__func__,
avs2_dec->lcu_size_log2,
data32);
WRITE_VREG(HEVC_SAO_CTRL0, data32);
#ifndef AVS2_10B_MMU
if ((get_double_write_mode(dec) & 0x10) == 0)
WRITE_VREG(HEVC_CM_BODY_START_ADDR, cur_pic->mc_y_adr);
#endif
if (get_double_write_mode