blob: 0728a0ddea2b9322a019f1d7b546539c40e432f8 [file] [log] [blame]
/*
* drivers/amlogic/amports/vh265.c
*
* Copyright (C) 2015 Amlogic, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*/
#define DEBUG
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/semaphore.h>
#include <linux/delay.h>
#include <linux/timer.h>
#include <linux/kfifo.h>
#include <linux/kthread.h>
#include <linux/platform_device.h>
#include <linux/amlogic/media/vfm/vframe.h>
#include <linux/amlogic/media/utils/amstream.h>
#include <linux/amlogic/media/utils/vformat.h>
#include <linux/amlogic/media/frame_sync/ptsserv.h>
#include <linux/amlogic/media/canvas/canvas.h>
#include <linux/amlogic/media/vfm/vframe.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/mm.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 "../utils/config_parser.h"
#include "../utils/firmware.h"
#include "../../../common/chips/decoder_cpu_ver_info.h"
#include "../utils/vdec_v4l2_buffer_ops.h"
#include <media/v4l2-mem2mem.h>
/*
to enable DV of frame mode
#define DOLBY_META_SUPPORT in ucode
*/
#define HEVC_8K_LFTOFFSET_FIX
#define SUPPORT_LONG_TERM_RPS
#define CONSTRAIN_MAX_BUF_NUM
#define SWAP_HEVC_UCODE
#define DETREFILL_ENABLE
#define AGAIN_HAS_THRESHOLD
/*#define TEST_NO_BUF*/
#define HEVC_PIC_STRUCT_SUPPORT
#define MULTI_INSTANCE_SUPPORT
#define USE_UNINIT_SEMA
/* .buf_size = 0x100000*16,
//4k2k , 0x100000 per buffer */
/* 4096x2304 , 0x120000 per buffer */
#define MPRED_8K_MV_BUF_SIZE (0x120000*4)
#define MPRED_4K_MV_BUF_SIZE (0x120000)
#define MPRED_MV_BUF_SIZE (0x3fc00)
#define MMU_COMPRESS_HEADER_SIZE_1080P 0x10000
#define MMU_COMPRESS_HEADER_SIZE_4K 0x48000
#define MMU_COMPRESS_HEADER_SIZE_8K 0x120000
#define DB_NUM 20
#define MAX_FRAME_4K_NUM 0x1200
#define MAX_FRAME_8K_NUM (0x1200*4)
//#define FRAME_MMU_MAP_SIZE (MAX_FRAME_4K_NUM * 4)
#define H265_MMU_MAP_BUFFER HEVC_ASSIST_SCRATCH_7
#define HEVC_ASSIST_MMU_MAP_ADDR 0x3009
#define HEVC_CM_HEADER_START_ADDR 0x3628
#define HEVC_SAO_MMU_VH1_ADDR 0x363b
#define HEVC_SAO_MMU_VH0_ADDR 0x363a
#define HEVC_DBLK_CFGB 0x350b
#define HEVCD_MPP_DECOMP_AXIURG_CTL 0x34c7
#define SWAP_HEVC_OFFSET (3 * 0x1000)
#define MEM_NAME "codec_265"
/* #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>
#define SEND_LMEM_WITH_RPM
#define SUPPORT_10BIT
/* #define ERROR_HANDLE_DEBUG */
#ifndef STAT_KTHREAD
#define STAT_KTHREAD 0x40
#endif
#ifdef MULTI_INSTANCE_SUPPORT
#define MAX_DECODE_INSTANCE_NUM 9
#define MULTI_DRIVER_NAME "ammvdec_h265"
#endif
#define DRIVER_NAME "amvdec_h265"
#define DRIVER_HEADER_NAME "amvdec_h265_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)
#define MAX_SIZE_8K (8192 * 4608)
#define MAX_SIZE_4K (4096 * 2304)
#define IS_8K_SIZE(w, h) (((w) * (h)) > MAX_SIZE_4K)
#define IS_4K_SIZE(w, h) (((w) * (h)) > (1920*1088))
#define SEI_UserDataITU_T_T35 4
#define INVALID_IDX -1 /* Invalid buffer index.*/
static struct semaphore h265_sema;
struct hevc_state_s;
static int hevc_print(struct hevc_state_s *hevc,
int debug_flag, const char *fmt, ...);
static int hevc_print_cont(struct hevc_state_s *hevc,
int debug_flag, const char *fmt, ...);
static int vh265_vf_states(struct vframe_states *states, void *);
static struct vframe_s *vh265_vf_peek(void *);
static struct vframe_s *vh265_vf_get(void *);
static void vh265_vf_put(struct vframe_s *, void *);
static int vh265_event_cb(int type, void *data, void *private_data);
static int vh265_stop(struct hevc_state_s *hevc);
#ifdef MULTI_INSTANCE_SUPPORT
static int vmh265_stop(struct hevc_state_s *hevc);
static s32 vh265_init(struct vdec_s *vdec);
static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask);
static void reset_process_time(struct hevc_state_s *hevc);
static void start_process_time(struct hevc_state_s *hevc);
static void restart_process_time(struct hevc_state_s *hevc);
static void timeout_process(struct hevc_state_s *hevc);
#else
static s32 vh265_init(struct hevc_state_s *hevc);
#endif
static void vh265_prot_init(struct hevc_state_s *hevc);
static int vh265_local_init(struct hevc_state_s *hevc);
static void vh265_check_timer_func(unsigned long arg);
static void config_decode_mode(struct hevc_state_s *hevc);
static int check_data_size(struct vdec_s *vdec);
static const char vh265_dec_id[] = "vh265-dev";
#define PROVIDER_NAME "decoder.h265"
#define MULTI_INSTANCE_PROVIDER_NAME "vdec.h265"
static const struct vframe_operations_s vh265_vf_provider = {
.peek = vh265_vf_peek,
.get = vh265_vf_get,
.put = vh265_vf_put,
.event_cb = vh265_event_cb,
.vf_states = vh265_vf_states,
};
static struct vframe_provider_s vh265_vf_prov;
static u32 bit_depth_luma;
static u32 bit_depth_chroma;
static u32 video_signal_type;
static int start_decode_buf_level = 0x8000;
static unsigned int decode_timeout_val = 200;
static u32 run_ready_min_buf_num = 2;
static u32 disable_ip_mode;
static u32 print_lcu_error = 1;
/*data_resend_policy:
bit 0, stream base resend data when decoding buf empty
*/
static u32 data_resend_policy = 1;
static int poc_num_margin = 1000;
static int poc_error_limit = 30;
static u32 dirty_again_threshold = 100;
static u32 dirty_buffersize_threshold = 0x800000;
#define VIDEO_SIGNAL_TYPE_AVAILABLE_MASK 0x20000000
/*
static const char * const video_format_names[] = {
"component", "PAL", "NTSC", "SECAM",
"MAC", "unspecified", "unspecified", "unspecified"
};
static const char * const color_primaries_names[] = {
"unknown", "bt709", "undef", "unknown",
"bt470m", "bt470bg", "smpte170m", "smpte240m",
"film", "bt2020"
};
static const char * const transfer_characteristics_names[] = {
"unknown", "bt709", "undef", "unknown",
"bt470m", "bt470bg", "smpte170m", "smpte240m",
"linear", "log100", "log316", "iec61966-2-4",
"bt1361e", "iec61966-2-1", "bt2020-10", "bt2020-12",
"smpte-st-2084", "smpte-st-428"
};
static const char * const matrix_coeffs_names[] = {
"GBR", "bt709", "undef", "unknown",
"fcc", "bt470bg", "smpte170m", "smpte240m",
"YCgCo", "bt2020nc", "bt2020c"
};
*/
#ifdef SUPPORT_10BIT
#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 HEVC_SAO_CTRL9 0x362d
#define LOSLESS_COMPRESS_MODE
/* 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;
* 5, (1/2):(1/2) ratio, with both compressed frame included
* 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;
* 0x1000,if > 1080p,use mode 3, else if > 960*540, use mode 4, else use mode 1;
*/
static u32 double_write_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 workaround_enable;
static u32 force_w_h;
#endif
static u32 force_fps;
static u32 pts_unstable;
#define H265_DEBUG_BUFMGR 0x01
#define H265_DEBUG_BUFMGR_MORE 0x02
#define H265_DEBUG_DETAIL 0x04
#define H265_DEBUG_REG 0x08
#define H265_DEBUG_MAN_SEARCH_NAL 0x10
#define H265_DEBUG_MAN_SKIP_NAL 0x20
#define H265_DEBUG_DISPLAY_CUR_FRAME 0x40
#define H265_DEBUG_FORCE_CLK 0x80
#define H265_DEBUG_SEND_PARAM_WITH_REG 0x100
#define H265_DEBUG_NO_DISPLAY 0x200
#define H265_DEBUG_DISCARD_NAL 0x400
#define H265_DEBUG_OUT_PTS 0x800
#define H265_DEBUG_DUMP_PIC_LIST 0x1000
#define H265_DEBUG_PRINT_SEI 0x2000
#define H265_DEBUG_PIC_STRUCT 0x4000
#define H265_DEBUG_HAS_AUX_IN_SLICE 0x8000
#define H265_DEBUG_DIS_LOC_ERROR_PROC 0x10000
#define H265_DEBUG_DIS_SYS_ERROR_PROC 0x20000
#define H265_NO_CHANG_DEBUG_FLAG_IN_CODE 0x40000
#define H265_DEBUG_TRIG_SLICE_SEGMENT_PROC 0x80000
#define H265_DEBUG_HW_RESET 0x100000
#define H265_CFG_CANVAS_IN_DECODE 0x200000
#define H265_DEBUG_DV 0x400000
#define H265_DEBUG_NO_EOS_SEARCH_DONE 0x800000
#define H265_DEBUG_NOT_USE_LAST_DISPBUF 0x1000000
#define H265_DEBUG_IGNORE_CONFORMANCE_WINDOW 0x2000000
#define H265_DEBUG_WAIT_DECODE_DONE_WHEN_STOP 0x4000000
#ifdef MULTI_INSTANCE_SUPPORT
#define PRINT_FLAG_ERROR 0x0
#define IGNORE_PARAM_FROM_CONFIG 0x08000000
#define PRINT_FRAMEBASE_DATA 0x10000000
#define PRINT_FLAG_VDEC_STATUS 0x20000000
#define PRINT_FLAG_VDEC_DETAIL 0x40000000
#define PRINT_FLAG_V4L_DETAIL 0x80000000
#endif
#define BUF_POOL_SIZE 32
#define MAX_BUF_NUM 24
#define MAX_REF_PIC_NUM 24
#define MAX_REF_ACTIVE 16
#ifdef MV_USE_FIXED_BUF
#define BMMU_MAX_BUFFERS (BUF_POOL_SIZE + 1)
#define VF_BUFFER_IDX(n) (n)
#define BMMU_WORKSPACE_ID (BUF_POOL_SIZE)
#else
#define BMMU_MAX_BUFFERS (BUF_POOL_SIZE + 1 + MAX_REF_PIC_NUM)
#define VF_BUFFER_IDX(n) (n)
#define BMMU_WORKSPACE_ID (BUF_POOL_SIZE)
#define MV_BUFFER_IDX(n) (BUF_POOL_SIZE + 1 + n)
#endif
#define HEVC_MV_INFO 0x310d
#define HEVC_QP_INFO 0x3137
#define HEVC_SKIP_INFO 0x3136
const u32 h265_version = 201602101;
static u32 debug_mask = 0xffffffff;
static u32 log_mask;
static u32 debug;
static u32 radr;
static u32 rval;
static u32 dbg_cmd;
static u32 dump_nal;
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 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 decode_pic_begin;
static uint slice_parse_begin;
static u32 step;
static bool is_reset;
#ifdef CONSTRAIN_MAX_BUF_NUM
static u32 run_ready_max_vf_only_num;
static u32 run_ready_display_q_num;
/*0: not check
0xff: work_pic_num
*/
static u32 run_ready_max_buf_num = 0xff;
#endif
static u32 dynamic_buf_num_margin = 7;
static u32 buf_alloc_width;
static u32 buf_alloc_height;
static u32 max_buf_num = 16;
static u32 buf_alloc_size;
/*static u32 re_config_pic_flag;*/
/*
*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 h265) 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[1:0]PB_skip_mode: 0, start decoding at begin;
*1, start decoding after first I;
*2, only decode and display none error picture;
*3, start decoding and display after IDR,etc
*bit[31:16] PB_skip_count_after_decoding (decoding but not display),
*only for mode 0 and 1.
*/
static u32 nal_skip_policy = 2;
/*
*bit 0, 1: only display I picture;
*bit 1, 1: only decode I picture;
*/
static u32 i_only_flag;
static u32 skip_nal_count = 500;
/*
bit 0, fast output first I picture
*/
static u32 fast_output_enable = 1;
static u32 frmbase_cont_bitlevel = 0x60;
/*
use_cma: 1, use both reserver memory and cma for buffers
2, only use cma for buffers
*/
static u32 use_cma = 2;
#define AUX_BUF_ALIGN(adr) ((adr + 0xf) & (~0xf))
/*
static u32 prefix_aux_buf_size = (16 * 1024);
static u32 suffix_aux_buf_size;
*/
static u32 prefix_aux_buf_size = (12 * 1024);
static u32 suffix_aux_buf_size = (12 * 1024);
static u32 max_decoding_time;
/*
*error handling
*/
/*error_handle_policy:
*bit 0: 0, auto skip error_skip_nal_count nals before error recovery;
*1, skip error_skip_nal_count nals before error recovery;
*bit 1 (valid only when bit0 == 1):
*1, wait vps/sps/pps after error recovery;
*bit 2 (valid only when bit0 == 0):
*0, auto search after error recovery (hevc_recover() called);
*1, manual search after error recovery
*(change to auto search after get IDR: WRITE_VREG(NAL_SEARCH_CTL, 0x2))
*
*bit 4: 0, set error_mark after reset/recover
* 1, do not set error_mark after reset/recover
*
*bit 5: 0, check total lcu for every picture
* 1, do not check total lcu
*
*bit 6: 0, do not check head error
* 1, check head error
*
*bit 7: 0, allow to print over decode
* 1, NOT allow to print over decode
*
*bit 8: 0, use interlace policy
* 1, NOT use interlace policy
*bit 9: 0, discard dirty data on playback start
* 1, do not discard dirty data on playback start
*bit 10:0, when ucode always returns again, it supports discarding data
* 1, When ucode always returns again, it does not support discarding data
*
*/
static u32 error_handle_policy;
static u32 error_skip_nal_count = 6;
static u32 error_handle_threshold = 30;
static u32 error_handle_nal_skip_threshold = 10;
static u32 error_handle_system_threshold = 30;
static u32 interlace_enable = 1;
static u32 fr_hint_status;
/*
*parser_sei_enable:
* bit 0, sei;
* bit 1, sei_suffix (fill aux buf)
* bit 2, fill sei to aux buf (when bit 0 is 1)
* bit 8, debug flag
*/
static u32 parser_sei_enable;
static u32 parser_dolby_vision_enable = 1;
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
static u32 dolby_meta_with_el;
static u32 dolby_el_flush_th = 2;
#endif
/* this is only for h265 mmu enable */
static u32 mmu_enable = 1;
static u32 mmu_enable_force;
static u32 work_buf_size;
static unsigned int force_disp_pic_index;
static unsigned int disp_vframe_valve_level;
static int pre_decode_buf_level = 0x1000;
static unsigned int pic_list_debug;
#ifdef HEVC_8K_LFTOFFSET_FIX
/* performance_profile: bit 0, multi slice in ucode
*/
static unsigned int performance_profile = 1;
#endif
#ifdef MULTI_INSTANCE_SUPPORT
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 max_get_frame_interval[MAX_DECODE_INSTANCE_NUM];
static unsigned int run_count[MAX_DECODE_INSTANCE_NUM];
static unsigned int input_empty[MAX_DECODE_INSTANCE_NUM];
static unsigned int not_run_ready[MAX_DECODE_INSTANCE_NUM];
static unsigned int ref_frame_mark_flag[MAX_DECODE_INSTANCE_NUM] =
{1, 1, 1, 1, 1, 1, 1, 1, 1};
#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
static unsigned char get_idx(struct hevc_state_s *hevc);
#endif
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
static u32 dv_toggle_prov_name;
static u32 dv_debug;
static u32 force_bypass_dvenl;
#endif
#endif
/*
*[3:0] 0: default use config from omx.
* 1: force enable fence.
* 2: disable fence.
*[7:4] 0: fence use for driver.
* 1: fence fd use for app.
*/
static u32 force_config_fence;
/*
*The parameter sps_max_dec_pic_buffering_minus1_0+1
*in SPS is the minimum DPB size required for stream
*(note: this parameter does not include the frame
*currently being decoded) +1 (decoding the current
*frame) +1 (decoding the current frame will only
*update refrence frame information, such as reference
*relation, when the next frame is decoded)
*/
static u32 detect_stuck_buffer_margin = 3;
#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
#define get_dbg_flag(hevc) ((debug_mask & (1 << hevc->index)) ? debug : 0)
#define get_dbg_flag2(hevc) ((debug_mask & (1 << get_idx(hevc))) ? debug : 0)
#define is_log_enable(hevc) ((log_mask & (1 << hevc->index)) ? 1 : 0)
#else
#define get_dbg_flag(hevc) debug
#define get_dbg_flag2(hevc) debug
#define is_log_enable(hevc) (log_mask ? 1 : 0)
#define get_valid_double_write_mode(hevc) double_write_mode
#define get_buf_alloc_width(hevc) buf_alloc_width
#define get_buf_alloc_height(hevc) buf_alloc_height
#define get_dynamic_buf_num_margin(hevc) dynamic_buf_num_margin
#endif
#define get_buffer_mode(hevc) buffer_mode
static DEFINE_SPINLOCK(lock);
struct task_struct *h265_task = NULL;
#undef DEBUG_REG
#ifdef DEBUG_REG
void WRITE_VREG_DBG(unsigned adr, unsigned val)
{
if (debug & H265_DEBUG_REG)
pr_info("%s(%x, %x)\n", __func__, adr, val);
WRITE_VREG(adr, val);
}
#undef WRITE_VREG
#define WRITE_VREG WRITE_VREG_DBG
#endif
extern u32 trickmode_i;
static DEFINE_MUTEX(vh265_mutex);
static DEFINE_MUTEX(vh265_log_mutex);
//static struct vdec_info *gvs;
static u32 without_display_mode;
static u32 mv_buf_dynamic_alloc;
/**************************************************
*
*h265 buffer management include
*
***************************************************
*/
enum NalUnitType {
NAL_UNIT_CODED_SLICE_TRAIL_N = 0, /* 0 */
NAL_UNIT_CODED_SLICE_TRAIL_R, /* 1 */
NAL_UNIT_CODED_SLICE_TSA_N, /* 2 */
/* Current name in the spec: TSA_R */
NAL_UNIT_CODED_SLICE_TLA, /* 3 */
NAL_UNIT_CODED_SLICE_STSA_N, /* 4 */
NAL_UNIT_CODED_SLICE_STSA_R, /* 5 */
NAL_UNIT_CODED_SLICE_RADL_N, /* 6 */
/* Current name in the spec: RADL_R */
NAL_UNIT_CODED_SLICE_DLP, /* 7 */
NAL_UNIT_CODED_SLICE_RASL_N, /* 8 */
/* Current name in the spec: RASL_R */
NAL_UNIT_CODED_SLICE_TFD, /* 9 */
NAL_UNIT_RESERVED_10,
NAL_UNIT_RESERVED_11,
NAL_UNIT_RESERVED_12,
NAL_UNIT_RESERVED_13,
NAL_UNIT_RESERVED_14,
NAL_UNIT_RESERVED_15,
/* Current name in the spec: BLA_W_LP */
NAL_UNIT_CODED_SLICE_BLA, /* 16 */
/* Current name in the spec: BLA_W_DLP */
NAL_UNIT_CODED_SLICE_BLANT, /* 17 */
NAL_UNIT_CODED_SLICE_BLA_N_LP, /* 18 */
/* Current name in the spec: IDR_W_DLP */
NAL_UNIT_CODED_SLICE_IDR, /* 19 */
NAL_UNIT_CODED_SLICE_IDR_N_LP, /* 20 */
NAL_UNIT_CODED_SLICE_CRA, /* 21 */
NAL_UNIT_RESERVED_22,
NAL_UNIT_RESERVED_23,
NAL_UNIT_RESERVED_24,
NAL_UNIT_RESERVED_25,
NAL_UNIT_RESERVED_26,
NAL_UNIT_RESERVED_27,
NAL_UNIT_RESERVED_28,
NAL_UNIT_RESERVED_29,
NAL_UNIT_RESERVED_30,
NAL_UNIT_RESERVED_31,
NAL_UNIT_VPS, /* 32 */
NAL_UNIT_SPS, /* 33 */
NAL_UNIT_PPS, /* 34 */
NAL_UNIT_ACCESS_UNIT_DELIMITER, /* 35 */
NAL_UNIT_EOS, /* 36 */
NAL_UNIT_EOB, /* 37 */
NAL_UNIT_FILLER_DATA, /* 38 */
NAL_UNIT_SEI, /* 39 Prefix SEI */
NAL_UNIT_SEI_SUFFIX, /* 40 Suffix SEI */
NAL_UNIT_RESERVED_41,
NAL_UNIT_RESERVED_42,
NAL_UNIT_RESERVED_43,
NAL_UNIT_RESERVED_44,
NAL_UNIT_RESERVED_45,
NAL_UNIT_RESERVED_46,
NAL_UNIT_RESERVED_47,
NAL_UNIT_UNSPECIFIED_48,
NAL_UNIT_UNSPECIFIED_49,
NAL_UNIT_UNSPECIFIED_50,
NAL_UNIT_UNSPECIFIED_51,
NAL_UNIT_UNSPECIFIED_52,
NAL_UNIT_UNSPECIFIED_53,
NAL_UNIT_UNSPECIFIED_54,
NAL_UNIT_UNSPECIFIED_55,
NAL_UNIT_UNSPECIFIED_56,
NAL_UNIT_UNSPECIFIED_57,
NAL_UNIT_UNSPECIFIED_58,
NAL_UNIT_UNSPECIFIED_59,
NAL_UNIT_UNSPECIFIED_60,
NAL_UNIT_UNSPECIFIED_61,
NAL_UNIT_UNSPECIFIED_62,
NAL_UNIT_UNSPECIFIED_63,
NAL_UNIT_INVALID,
};
/* --------------------------------------------------- */
/* Amrisc Software Interrupt */
/* --------------------------------------------------- */
#define AMRISC_STREAM_EMPTY_REQ 0x01
#define AMRISC_PARSER_REQ 0x02
#define AMRISC_MAIN_REQ 0x04
/* --------------------------------------------------- */
/* HEVC_DEC_STATUS define */
/* --------------------------------------------------- */
#define HEVC_DEC_IDLE 0x0
#define HEVC_NAL_UNIT_VPS 0x1
#define HEVC_NAL_UNIT_SPS 0x2
#define HEVC_NAL_UNIT_PPS 0x3
#define HEVC_NAL_UNIT_CODED_SLICE_SEGMENT 0x4
#define HEVC_CODED_SLICE_SEGMENT_DAT 0x5
#define HEVC_SLICE_DECODING 0x6
#define HEVC_NAL_UNIT_SEI 0x7
#define HEVC_SLICE_SEGMENT_DONE 0x8
#define HEVC_NAL_SEARCH_DONE 0x9
#define HEVC_DECPIC_DATA_DONE 0xa
#define HEVC_DECPIC_DATA_ERROR 0xb
#define HEVC_SEI_DAT 0xc
#define HEVC_SEI_DAT_DONE 0xd
#define HEVC_NAL_DECODE_DONE 0xe
#define HEVC_OVER_DECODE 0xf
#define HEVC_DATA_REQUEST 0x12
#define HEVC_DECODE_BUFEMPTY 0x20
#define HEVC_DECODE_TIMEOUT 0x21
#define HEVC_SEARCH_BUFEMPTY 0x22
#define HEVC_DECODE_OVER_SIZE 0x23
#define HEVC_DECODE_BUFEMPTY2 0x24
#define HEVC_FIND_NEXT_PIC_NAL 0x50
#define HEVC_FIND_NEXT_DVEL_NAL 0x51
#define HEVC_DUMP_LMEM 0x30
#define HEVC_4k2k_60HZ_NOT_SUPPORT 0x80
#define HEVC_DISCARD_NAL 0xf0
#define HEVC_ACTION_DEC_CONT 0xfd
#define HEVC_ACTION_ERROR 0xfe
#define HEVC_ACTION_DONE 0xff
/* --------------------------------------------------- */
/* 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
/**************************************************
*
*h265 buffer management
*
***************************************************
*/
/* #define BUFFER_MGR_ONLY */
/* #define CONFIG_HEVC_CLK_FORCED_ON */
/* #define ENABLE_SWAP_TEST */
#define MCRCC_ENABLE
#define INVALID_POC 0x80000000
#define HEVC_DEC_STATUS_REG HEVC_ASSIST_SCRATCH_0
#define HEVC_RPM_BUFFER HEVC_ASSIST_SCRATCH_1
#define HEVC_SHORT_TERM_RPS HEVC_ASSIST_SCRATCH_2
#define HEVC_VPS_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
#define HEVC_STREAM_SWAP_BUFFER HEVC_ASSIST_SCRATCH_7
#define HEVC_STREAM_SWAP_BUFFER2 HEVC_ASSIST_SCRATCH_8
#define HEVC_sao_mem_unit HEVC_ASSIST_SCRATCH_9
#define HEVC_SAO_ABV HEVC_ASSIST_SCRATCH_A
#define HEVC_sao_vb_size HEVC_ASSIST_SCRATCH_B
#define HEVC_SAO_VB 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_F
#ifdef ENABLE_SWAP_TEST
#define HEVC_STREAM_SWAP_TEST HEVC_ASSIST_SCRATCH_L
#endif
/*#define HEVC_DECODE_PIC_BEGIN_REG HEVC_ASSIST_SCRATCH_M*/
/*#define HEVC_DECODE_PIC_NUM_REG HEVC_ASSIST_SCRATCH_N*/
#define HEVC_DECODE_SIZE HEVC_ASSIST_SCRATCH_N
/*do not define ENABLE_SWAP_TEST*/
#define HEVC_AUX_ADR HEVC_ASSIST_SCRATCH_L
#define HEVC_AUX_DATA_SIZE HEVC_ASSIST_SCRATCH_M
#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/fetch SEI in ucode;
* 1, parse/fetch SEI in ucode
*bit [18]: for NAL_SEI_SUFFIX when bit0 is 0:
* 0, do not fetch NAL_SEI_SUFFIX to aux buf;
* 1, fetch NAL_SEL_SUFFIX data to aux buf
*bit [19]:
* 0, parse NAL_SEI in ucode
* 1, fetch NAL_SEI to aux buf
*bit [20]: for DOLBY_VISION_META
* 0, do not fetch DOLBY_VISION_META to aux buf
* 1, fetch DOLBY_VISION_META to aux buf
*/
#define NAL_SEARCH_CTL HEVC_ASSIST_SCRATCH_I
/*read only*/
#define CUR_NAL_UNIT_TYPE HEVC_ASSIST_SCRATCH_J
/*
[15 : 8] rps_set_id
[7 : 0] start_decoding_flag
*/
#define HEVC_DECODE_INFO HEVC_ASSIST_SCRATCH_1
/*set before start decoder*/
#define HEVC_DECODE_MODE HEVC_ASSIST_SCRATCH_J
#define HEVC_DECODE_MODE2 HEVC_ASSIST_SCRATCH_H
#define DECODE_STOP_POS HEVC_ASSIST_SCRATCH_K
#define DECODE_MODE_SINGLE 0x0
#define DECODE_MODE_MULTI_FRAMEBASE 0x1
#define DECODE_MODE_MULTI_STREAMBASE 0x2
#define DECODE_MODE_MULTI_DVBAL 0x3
#define DECODE_MODE_MULTI_DVENL 0x4
#define MAX_INT 0x7FFFFFFF
#define RPM_BEGIN 0x100
#define modification_list_cur 0x148
#define RPM_END 0x180
#ifdef SUPPORT_LONG_TERM_RPS
/*
*/
#define RPS_END 0x8000
#define RPS_LT_BIT 14
#define RPS_USED_BIT 13
#define RPS_SIGN_BIT 12
#else
#define RPS_END 0x8000
#define RPS_USED_BIT 14
#define RPS_SIGN_BIT 13
#endif
/* MISC_FLAG0 */
#define PCM_LOOP_FILTER_DISABLED_FLAG_BIT 0
#define PCM_ENABLE_FLAG_BIT 1
#define LOOP_FILER_ACROSS_TILES_ENABLED_FLAG_BIT 2
#define PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED_FLAG_BIT 3
#define DEBLOCKING_FILTER_OVERRIDE_ENABLED_FLAG_BIT 4
#define PPS_DEBLOCKING_FILTER_DISABLED_FLAG_BIT 5
#define DEBLOCKING_FILTER_OVERRIDE_FLAG_BIT 6
#define SLICE_DEBLOCKING_FILTER_DISABLED_FLAG_BIT 7
#define SLICE_SAO_LUMA_FLAG_BIT 8
#define SLICE_SAO_CHROMA_FLAG_BIT 9
#define SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED_FLAG_BIT 10
union param_u {
struct {
unsigned short data[RPM_END - RPM_BEGIN];
} l;
struct {
/* from ucode lmem, do not change this struct */
unsigned short CUR_RPS[0x10];
unsigned short num_ref_idx_l0_active;
unsigned short num_ref_idx_l1_active;
unsigned short slice_type;
unsigned short slice_temporal_mvp_enable_flag;
unsigned short dependent_slice_segment_flag;
unsigned short slice_segment_address;
unsigned short num_title_rows_minus1;
unsigned short pic_width_in_luma_samples;
unsigned short pic_height_in_luma_samples;
unsigned short log2_min_coding_block_size_minus3;
unsigned short log2_diff_max_min_coding_block_size;
unsigned short log2_max_pic_order_cnt_lsb_minus4;
unsigned short POClsb;
unsigned short collocated_from_l0_flag;
unsigned short collocated_ref_idx;
unsigned short log2_parallel_merge_level;
unsigned short five_minus_max_num_merge_cand;
unsigned short sps_num_reorder_pics_0;
unsigned short modification_flag;
unsigned short tiles_enabled_flag;
unsigned short num_tile_columns_minus1;
unsigned short num_tile_rows_minus1;
unsigned short tile_width[12];
unsigned short tile_height[8];
unsigned short misc_flag0;
unsigned short pps_beta_offset_div2;
unsigned short pps_tc_offset_div2;
unsigned short slice_beta_offset_div2;
unsigned short slice_tc_offset_div2;
unsigned short pps_cb_qp_offset;
unsigned short pps_cr_qp_offset;
unsigned short first_slice_segment_in_pic_flag;
unsigned short m_temporalId;
unsigned short m_nalUnitType;
unsigned short vui_num_units_in_tick_hi;
unsigned short vui_num_units_in_tick_lo;
unsigned short vui_time_scale_hi;
unsigned short vui_time_scale_lo;
unsigned short bit_depth;
unsigned short profile_etc;
unsigned short sei_frame_field_info;
unsigned short video_signal_type;
unsigned short modification_list[0x20];
unsigned short conformance_window_flag;
unsigned short conf_win_left_offset;
unsigned short conf_win_right_offset;
unsigned short conf_win_top_offset;
unsigned short conf_win_bottom_offset;
unsigned short chroma_format_idc;
unsigned short color_description;
unsigned short aspect_ratio_idc;
unsigned short sar_width;
unsigned short sar_height;
unsigned short sps_max_dec_pic_buffering_minus1_0;
} p;
};
#define RPM_BUF_SIZE (0x80*2)
/* non mmu mode lmem size : 0x400, mmu mode : 0x500*/
#define LMEM_BUF_SIZE (0x500 * 2)
struct buff_s {
u32 buf_start;
u32 buf_size;
u32 buf_end;
};
struct BuffInfo_s {
u32 max_width;
u32 max_height;
unsigned int start_adr;
unsigned int end_adr;
struct buff_s ipp;
struct buff_s sao_abv;
struct buff_s sao_vb;
struct buff_s short_term_rps;
struct buff_s vps;
struct buff_s sps;
struct buff_s pps;
struct buff_s sao_up;
struct buff_s swap_buf;
struct buff_s swap_buf2;
struct buff_s scalelut;
struct buff_s dblk_para;
struct buff_s dblk_data;
struct buff_s dblk_data2;
struct buff_s mmu_vbh;
struct buff_s cm_header;
struct buff_s mpred_above;
#ifdef MV_USE_FIXED_BUF
struct buff_s mpred_mv;
#endif
struct buff_s rpm;
struct buff_s lmem;
};
//#define VBH_BUF_SIZE (2 * 16 * 2304)
//#define VBH_BUF_COUNT 4
/*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 amvh265_workbuff_spec[WORK_BUF_SPEC_NUM] = {
{
/* 8M bytes */
.max_width = 1920,
.max_height = 1088,
.ipp = {/*checked*/
/* IPP work space calculation :
* 4096 * (Y+CbCr+Flags) = 12k, round to 16k
*/
.buf_size = 0x1e00,
},
.sao_abv = {
.buf_size = 0, //0x30000,
},
.sao_vb = {
.buf_size = 0, //0x30000,
},
.short_term_rps = {/*checked*/
/* SHORT_TERM_RPS - Max 64 set, 16 entry every set,
* total 64x16x2 = 2048 bytes (0x800)
*/
.buf_size = 0x800,
},
.vps = {/*checked*/
/* VPS STORE AREA - Max 16 VPS, each has 0x80 bytes,
* total 0x0800 bytes
*/
.buf_size = 0x800,
},
.sps = {/*checked*/
/* SPS STORE AREA - Max 16 SPS, each has 0x80 bytes,
* total 0x0800 bytes
*/
.buf_size = 0x800,
},
.pps = {/*checked*/
/* 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, //0x2800,
},
.swap_buf = {/*checked*/
/* 256cyclex64bit = 2K bytes 0x800
* (only 144 cycles valid)
*/
.buf_size = 0x800,
},
.swap_buf2 = {/*checked*/
.buf_size = 0x800,
},
.scalelut = {/*checked*/
/* support up to 32 SCALELUT 1024x32 =
* 32Kbytes (0x8000)
*/
.buf_size = 0x8000,
},
.dblk_para = {.buf_size = 0x14500, }, // dblk parameter
.dblk_data = {.buf_size = 0x62800, }, // dblk data for left/top
.dblk_data2 = {.buf_size = 0x22800, }, // dblk data for adapter
.mmu_vbh = {/*checked*/
.buf_size = VBH_BUF_SIZE_1080P, /*2*16*2304/4, 4K*/
},
#if 0
.cm_header = {/*checked*//* 0x44000 = ((1088*2*1024*4)/32/4)*(32/8)*/
.buf_size = MMU_COMPRESS_HEADER_SIZE_1080P *
(MAX_REF_PIC_NUM + 1),
},
#endif
.mpred_above = {/*checked*/
.buf_size = 0x1e00,
},
#ifdef MV_USE_FIXED_BUF
.mpred_mv = {/*checked*//* 1080p, 0x40000 per buffer */
.buf_size = MPRED_MV_BUF_SIZE * MAX_REF_PIC_NUM,
},
#endif
.rpm = {/*checked*/
.buf_size = RPM_BUF_SIZE,
},
.lmem = {/*checked*/
.buf_size = 0x500 * 2,
}
},
{
.max_width = 4096,
.max_height = 2048,
.ipp = {
/* IPP work space calculation :
* 4096 * (Y+CbCr+Flags) = 12k, round to 16k
*/
.buf_size = 0x4000,
},
.sao_abv = {
.buf_size = 0, //0x30000,
},
.sao_vb = {
.buf_size = 0, //0x30000,
},
.short_term_rps = {
/* SHORT_TERM_RPS - Max 64 set, 16 entry every set,
* total 64x16x2 = 2048 bytes (0x800)
*/
.buf_size = 0x800,
},
.vps = {
/* VPS STORE AREA - Max 16 VPS, each has 0x80 bytes,
* total 0x0800 bytes
*/
.buf_size = 0x800,
},
.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, //0x2800,
},
.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 = 0x8000,
},
.dblk_para = {.buf_size = 0x19100, }, // dblk parameter
.dblk_data = {.buf_size = 0x88800, }, // dblk data for left/top
.dblk_data2 = {.buf_size = 0x80000, }, // dblk data for adapter
.mmu_vbh = {
.buf_size = VBH_BUF_SIZE_4K, /*2*16*2304/4, 4K*/
},
#if 0
.cm_header = {/*0x44000 = ((1088*2*1024*4)/32/4)*(32/8)*/
.buf_size = MMU_COMPRESS_HEADER_SIZE_4K *
(MAX_REF_PIC_NUM + 1),
},
#endif
.mpred_above = {
.buf_size = 0x4000,
},
#ifdef MV_USE_FIXED_BUF
.mpred_mv = {
/* .buf_size = 0x100000*16,
//4k2k , 0x100000 per buffer */
/* 4096x2304 , 0x120000 per buffer */
.buf_size = MPRED_4K_MV_BUF_SIZE * MAX_REF_PIC_NUM,
},
#endif
.rpm = {
.buf_size = RPM_BUF_SIZE,
},
.lmem = {
.buf_size = 0x500 * 2,
}
},
{
.max_width = 4096*2,
.max_height = 2048*2,
.ipp = {
// IPP work space calculation : 4096 * (Y+CbCr+Flags) = 12k, round to 16k
.buf_size = 0x4000*2,
},
.sao_abv = {
.buf_size = 0, //0x30000*2,
},
.sao_vb = {
.buf_size = 0, //0x30000*2,
},
.short_term_rps = {
// SHORT_TERM_RPS - Max 64 set, 16 entry every set, total 64x16x2 = 2048 bytes (0x800)
.buf_size = 0x800,
},
.vps = {
// VPS STORE AREA - Max 16 VPS, each has 0x80 bytes, total 0x0800 bytes
.buf_size = 0x800,
},
.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, //0x2800*2,
},
.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 = 0x8000, //0x8000*2,
},
.dblk_para = {.buf_size = 0x32100, }, // dblk parameter
.dblk_data = {.buf_size = 0x110800, }, // dblk data for left/top
.dblk_data2 = {.buf_size = 0x90800, }, // dblk data for adapter
.mmu_vbh = {
.buf_size = VBH_BUF_SIZE_8K, //2*16*2304/4, 4K
},
#if 0
.cm_header = {
.buf_size = MMU_COMPRESS_HEADER_SIZE_8K *
MAX_REF_PIC_NUM, // 0x44000 = ((1088*2*1024*4)/32/4)*(32/8)
},
#endif
.mpred_above = {
.buf_size = 0x8000,
},
#ifdef MV_USE_FIXED_BUF
.mpred_mv = {
.buf_size = MPRED_8K_MV_BUF_SIZE * MAX_REF_PIC_NUM, //4k2k , 0x120000 per buffer
},
#endif
.rpm = {
.buf_size = RPM_BUF_SIZE,
},
.lmem = {
.buf_size = 0x500 * 2,
},
}
};
static void init_buff_spec(struct hevc_state_s *hevc,
struct BuffInfo_s *buf_spec)
{
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->vps.buf_start =
buf_spec->short_term_rps.buf_start +
buf_spec->short_term_rps.buf_size;
buf_spec->sps.buf_start =
buf_spec->vps.buf_start + buf_spec->vps.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;
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;
#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 (hevc && get_dbg_flag2(hevc)) {
hevc_print(hevc, 0,
"%s workspace (%x %x) size = %x\n", __func__,
buf_spec->start_adr, buf_spec->end_adr,
buf_spec->end_adr - buf_spec->start_adr);
hevc_print(hevc, 0,
"ipp.buf_start :%x\n",
buf_spec->ipp.buf_start);
hevc_print(hevc, 0,
"sao_abv.buf_start :%x\n",
buf_spec->sao_abv.buf_start);
hevc_print(hevc, 0,
"sao_vb.buf_start :%x\n",
buf_spec->sao_vb.buf_start);
hevc_print(hevc, 0,
"short_term_rps.buf_start :%x\n",
buf_spec->short_term_rps.buf_start);
hevc_print(hevc, 0,
"vps.buf_start :%x\n",
buf_spec->vps.buf_start);
hevc_print(hevc, 0,
"sps.buf_start :%x\n",
buf_spec->sps.buf_start);
hevc_print(hevc, 0,
"pps.buf_start :%x\n",
buf_spec->pps.buf_start);
hevc_print(hevc, 0,
"sao_up.buf_start :%x\n",
buf_spec->sao_up.buf_start);
hevc_print(hevc, 0,
"swap_buf.buf_start :%x\n",
buf_spec->swap_buf.buf_start);
hevc_print(hevc, 0,
"swap_buf2.buf_start :%x\n",
buf_spec->swap_buf2.buf_start);
hevc_print(hevc, 0,
"scalelut.buf_start :%x\n",
buf_spec->scalelut.buf_start);
hevc_print(hevc, 0,
"dblk_para.buf_start :%x\n",
buf_spec->dblk_para.buf_start);
hevc_print(hevc, 0,
"dblk_data.buf_start :%x\n",
buf_spec->dblk_data.buf_start);
hevc_print(hevc, 0,
"dblk_data2.buf_start :%x\n",
buf_spec->dblk_data2.buf_start);
hevc_print(hevc, 0,
"mpred_above.buf_start :%x\n",
buf_spec->mpred_above.buf_start);
#ifdef MV_USE_FIXED_BUF
hevc_print(hevc, 0,
"mpred_mv.buf_start :%x\n",
buf_spec->mpred_mv.buf_start);
#endif
if ((get_dbg_flag2(hevc)
&
H265_DEBUG_SEND_PARAM_WITH_REG)
== 0) {
hevc_print(hevc, 0,
"rpm.buf_start :%x\n",
buf_spec->rpm.buf_start);
}
}
}
enum SliceType {
B_SLICE,
P_SLICE,
I_SLICE
};
/*USE_BUF_BLOCK*/
struct BUF_s {
ulong start_adr;
u32 size;
u32 luma_size;
ulong header_addr;
u32 header_size;
int used_flag;
ulong v4l_ref_buf_addr;
ulong chroma_addr;
u32 chroma_size;
} /*BUF_t */;
/* level 6, 6.1 maximum slice number is 800; other is 200 */
#define MAX_SLICE_NUM 800
struct PIC_s {
int index;
int scatter_alloc;
int BUF_index;
int mv_buf_index;
int POC;
int decode_idx;
int slice_type;
int RefNum_L0;
int RefNum_L1;
int num_reorder_pic;
int stream_offset;
unsigned char referenced;
unsigned char output_mark;
unsigned char recon_mark;
unsigned char output_ready;
unsigned char error_mark;
//dis_mark = 0:discard mark,dis_mark = 1:no discard mark
unsigned char dis_mark;
/**/ int slice_idx;
int m_aiRefPOCList0[MAX_SLICE_NUM][16];
int m_aiRefPOCList1[MAX_SLICE_NUM][16];
#ifdef SUPPORT_LONG_TERM_RPS
unsigned char long_term_ref;
unsigned char m_aiRefLTflgList0[MAX_SLICE_NUM][16];
unsigned char m_aiRefLTflgList1[MAX_SLICE_NUM][16];
#endif
/*buffer */
unsigned int header_adr;
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
unsigned char dv_enhance_exist;
#endif
char *aux_data_buf;
int aux_data_size;
unsigned long cma_alloc_addr;
struct page *alloc_pages;
unsigned int mpred_mv_wr_start_addr;
int mv_size;
unsigned int mc_y_adr;
unsigned int mc_u_v_adr;
#ifdef SUPPORT_10BIT
/*unsigned int comp_body_size;*/
unsigned int dw_y_adr;
unsigned int dw_u_v_adr;
#endif
int mc_canvas_y;
int mc_canvas_u_v;
int width;
int height;
int y_canvas_index;
int uv_canvas_index;
#ifdef MULTI_INSTANCE_SUPPORT
struct canvas_config_s canvas_config[2];
#endif
#ifdef SUPPORT_10BIT
int mem_saving_mode;
u32 bit_depth_luma;
u32 bit_depth_chroma;
#endif
#ifdef LOSLESS_COMPRESS_MODE
unsigned int losless_comp_body_size;
#endif
unsigned char pic_struct;
int vf_ref;
u32 pts;
u64 pts64;
u64 timestamp;
u32 aspect_ratio_idc;
u32 sar_width;
u32 sar_height;
u32 double_write_mode;
u32 video_signal_type;
unsigned short conformance_window_flag;
unsigned short conf_win_left_offset;
unsigned short conf_win_right_offset;
unsigned short conf_win_top_offset;
unsigned short conf_win_bottom_offset;
unsigned short chroma_format_idc;
/* picture qos infomation*/
int max_qp;
int avg_qp;
int min_qp;
int max_skip;
int avg_skip;
int min_skip;
int max_mv;
int min_mv;
int avg_mv;
u32 hw_decode_time;
u32 frame_size; // For frame base mode
bool vframe_bound;
bool ip_mode;
u32 hdr10p_data_size;
char *hdr10p_data_buf;
struct fence *fence;
bool show_frame;
} /*PIC_t */;
#define MAX_TILE_COL_NUM 10
#define MAX_TILE_ROW_NUM 20
struct tile_s {
int width;
int height;
int start_cu_x;
int start_cu_y;
unsigned int sao_vb_start_addr;
unsigned int sao_abv_start_addr;
};
#define SEI_MASTER_DISPLAY_COLOR_MASK 0x00000001
#define SEI_CONTENT_LIGHT_LEVEL_MASK 0x00000002
#define SEI_HDR10PLUS_MASK 0x00000004
#define VF_POOL_SIZE 32
#ifdef MULTI_INSTANCE_SUPPORT
#define DEC_RESULT_NONE 0
#define DEC_RESULT_DONE 1
#define DEC_RESULT_AGAIN 2
#define DEC_RESULT_CONFIG_PARAM 3
#define DEC_RESULT_ERROR 4
#define DEC_INIT_PICLIST 5
#define DEC_UNINIT_PICLIST 6
#define DEC_RESULT_GET_DATA 7
#define DEC_RESULT_GET_DATA_RETRY 8
#define DEC_RESULT_EOS 9
#define DEC_RESULT_FORCE_EXIT 10
#define DEC_RESULT_FREE_CANVAS 11
#define DEC_RESULT_DISCARD_DATA 12
static void vh265_work(struct work_struct *work);
static void vh265_timeout_work(struct work_struct *work);
static void vh265_notify_work(struct work_struct *work);
#endif
struct debug_log_s {
struct list_head list;
uint8_t data; /*will alloc more size*/
};
struct hevc_state_s {
#ifdef MULTI_INSTANCE_SUPPORT
struct platform_device *platform_dev;
void (*vdec_cb)(struct vdec_s *, void *);
void *vdec_cb_arg;
struct vframe_chunk_s *chunk;
int dec_result;
u32 timeout_processing;
struct work_struct work;
struct work_struct timeout_work;
struct work_struct notify_work;
struct work_struct set_clk_work;
/* timeout handle */
unsigned long int start_process_time;
unsigned int last_lcu_idx;
unsigned int decode_timeout_count;
unsigned int timeout_num;
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
unsigned char switch_dvlayer_flag;
unsigned char no_switch_dvlayer_count;
unsigned char bypass_dvenl_enable;
unsigned char bypass_dvenl;
#endif
unsigned char start_parser_type;
/*start_decoding_flag:
vps/pps/sps/idr info from ucode*/
unsigned char start_decoding_flag;
unsigned char rps_set_id;
unsigned char eos;
int pic_decoded_lcu_idx;
u8 over_decode;
u8 empty_flag;
#endif
struct vframe_s vframe_dummy;
char *provider_name;
int index;
struct device *cma_dev;
unsigned char m_ins_flag;
unsigned char dolby_enhance_flag;
unsigned long buf_start;
u32 buf_size;
u32 mv_buf_size;
struct BuffInfo_s work_space_buf_store;
struct BuffInfo_s *work_space_buf;
u8 aux_data_dirty;
u32 prefix_aux_size;
u32 suffix_aux_size;
void *aux_addr;
void *rpm_addr;
void *lmem_addr;
dma_addr_t aux_phy_addr;
dma_addr_t rpm_phy_addr;
dma_addr_t lmem_phy_addr;
unsigned int pic_list_init_flag;
unsigned int use_cma_flag;
unsigned short *rpm_ptr;
unsigned short *lmem_ptr;
unsigned short *debug_ptr;
int debug_ptr_size;
int pic_w;
int pic_h;
int lcu_x_num;
int lcu_y_num;
int lcu_total;
int lcu_size;
int lcu_size_log2;
int lcu_x_num_pre;
int lcu_y_num_pre;
int first_pic_after_recover;
int num_tile_col;
int num_tile_row;
int tile_enabled;
int tile_x;
int tile_y;
int tile_y_x;
int tile_start_lcu_x;
int tile_start_lcu_y;
int tile_width_lcu;
int tile_height_lcu;
int slice_type;
unsigned int slice_addr;
unsigned int slice_segment_addr;
unsigned char interlace_flag;
unsigned char curr_pic_struct;
unsigned char frame_field_info_present_flag;
unsigned short sps_num_reorder_pics_0;
unsigned short misc_flag0;
int m_temporalId;
int m_nalUnitType;
int TMVPFlag;
int isNextSliceSegment;
int LDCFlag;
int m_pocRandomAccess;
int plevel;
int MaxNumMergeCand;
int new_pic;
int new_tile;
int curr_POC;
int iPrevPOC;
#ifdef MULTI_INSTANCE_SUPPORT
int decoded_poc;
struct PIC_s *decoding_pic;
#endif
int iPrevTid0POC;
int list_no;
int RefNum_L0;
int RefNum_L1;
int ColFromL0Flag;
int LongTerm_Curr;
int LongTerm_Col;
int Col_POC;
int LongTerm_Ref;
#ifdef MULTI_INSTANCE_SUPPORT
int m_pocRandomAccess_bak;
int curr_POC_bak;
int iPrevPOC_bak;
int iPrevTid0POC_bak;
unsigned char start_parser_type_bak;
unsigned char start_decoding_flag_bak;
unsigned char rps_set_id_bak;
int pic_decoded_lcu_idx_bak;
int decode_idx_bak;
#endif
struct PIC_s *cur_pic;
struct PIC_s *col_pic;
int skip_flag;
int decode_idx;
int slice_idx;
unsigned char have_vps;
unsigned char have_sps;
unsigned char have_pps;
unsigned char have_valid_start_slice;
unsigned char wait_buf;
unsigned char error_flag;
unsigned int error_skip_nal_count;
long used_4k_num;
unsigned char
ignore_bufmgr_error; /* bit 0, for decoding;
bit 1, for displaying
bit 1 must be set if bit 0 is 1*/
int PB_skip_mode;
int PB_skip_count_after_decoding;
#ifdef SUPPORT_10BIT
int mem_saving_mode;
#endif
#ifdef LOSLESS_COMPRESS_MODE
unsigned int losless_comp_body_size;
#endif
int pts_mode;
int last_lookup_pts;
int last_pts;
u64 last_lookup_pts_us64;
u64 last_pts_us64;
u32 shift_byte_count_lo;
u32 shift_byte_count_hi;
int pts_mode_switching_count;
int pts_mode_recovery_count;
int pic_num;
/**/
union param_u param;
struct tile_s m_tile[MAX_TILE_ROW_NUM][MAX_TILE_COL_NUM];
struct timer_list timer;
struct BUF_s m_BUF[BUF_POOL_SIZE];
struct BUF_s m_mv_BUF[MAX_REF_PIC_NUM];
struct PIC_s *m_PIC[MAX_REF_PIC_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 stat;
u32 frame_width;
u32 frame_height;
u32 frame_dur;
u32 frame_ar;
u32 bit_depth_luma;
u32 bit_depth_chroma;
u32 video_signal_type;
u32 video_signal_type_debug;
u32 saved_resolution;
bool get_frame_dur;
u32 error_watchdog_count;
u32 error_skip_nal_wt_cnt;
u32 error_system_watchdog_count;
#ifdef DEBUG_PTS
unsigned long pts_missed;
unsigned long pts_hit;
#endif
struct dec_sysinfo vh265_amstream_dec_info;
unsigned char init_flag;
unsigned char first_sc_checked;
unsigned char uninit_list;
u32 start_decoding_time;
int show_frame_num;
#ifdef USE_UNINIT_SEMA
struct semaphore h265_uninit_done_sema;
#endif
int fatal_error;
u32 sei_present_flag;
void *frame_mmu_map_addr;
dma_addr_t frame_mmu_map_phy_addr;
unsigned int mmu_mc_buf_start;
unsigned int mmu_mc_buf_end;
unsigned int mmu_mc_start_4k_adr;
void *mmu_box;
void *bmmu_box;
int mmu_enable;
unsigned int dec_status;
/* data for SEI_MASTER_DISPLAY_COLOR */
unsigned int primaries[3][2];
unsigned int white_point[2];
unsigned int luminance[2];
/* data for SEI_CONTENT_LIGHT_LEVEL */
unsigned int content_light_level[2];
struct PIC_s *pre_top_pic;
struct PIC_s *pre_bot_pic;
#ifdef MULTI_INSTANCE_SUPPORT
int double_write_mode;
int dynamic_buf_num_margin;
int start_action;
int save_buffer_mode;
#endif
u32 i_only;
struct list_head log_list;
u32 ucode_pause_pos;
u32 start_shift_bytes;
u32 vf_pre_count;
u32 vf_get_count;
u32 vf_put_count;
#ifdef SWAP_HEVC_UCODE
dma_addr_t mc_dma_handle;
void *mc_cpu_addr;
int swap_size;
ulong swap_addr;
#endif
#ifdef DETREFILL_ENABLE
dma_addr_t detbuf_adr;
u16 *detbuf_adr_virt;
u8 delrefill_check;
#endif
u8 head_error_flag;
int valve_count;
struct firmware_s *fw;
int max_pic_w;
int max_pic_h;
#ifdef AGAIN_HAS_THRESHOLD
u8 next_again_flag;
u32 pre_parser_wr_ptr;
#endif
u32 ratio_control;
u32 first_pic_flag;
u32 decode_size;
struct mutex chunks_mutex;
int need_cache_size;
u64 sc_start_time;
u32 skip_nal_count;
bool is_swap;
bool is_4k;
int frameinfo_enable;
struct vframe_qos_s vframe_qos;
bool is_used_v4l;
void *v4l2_ctx;
bool v4l_params_parsed;
u32 mem_map_mode;
u32 performance_profile;
struct vdec_info *gvs;
u32 res_ch_flag;
bool ip_mode;
u32 kpi_first_i_comming;
u32 kpi_first_i_decoded;
int sidebind_type;
int sidebind_channel_id;
u32 pre_parser_video_rp;
u32 pre_parser_video_wp;
bool dv_duallayer;
u32 poc_error_count;
u32 timeout_flag;
ulong timeout;
bool discard_dv_data;
bool enable_fence;
int fence_usage;
int low_latency_flag;
u32 dirty_shift_flag;
char vdec_name[32];
char set_canvas0_addr[32];
char get_canvas0_addr[32];
char put_canvas0_addr[32];
char vf_put_name[32];
char vf_get_name[32];
char new_q_name[32];
char disp_q_name[32];
char pts_name[32];
int dec_again_cnt;
} /*hevc_stru_t */;
#ifdef AGAIN_HAS_THRESHOLD
static u32 again_threshold;
#endif
#ifdef SEND_LMEM_WITH_RPM
#define get_lmem_params(hevc, ladr) \
hevc->lmem_ptr[ladr - (ladr & 0x3) + 3 - (ladr & 0x3)]
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 is_oversize(int w, int h)
{
int max = (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1)?
MAX_SIZE_8K : MAX_SIZE_4K;
if (w < 0 || h < 0)
return true;
if (h != 0 && (w > max / h))
return true;
return false;
}
int is_oversize_ex(int w, int h)
{
int max = (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) ?
MAX_SIZE_8K : MAX_SIZE_4K;
if (w == 0 || h == 0)
return true;
if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) {
if (w > 8192 || h > 4608)
return true;
} else {
if (w > 4096 || h > 2304)
return true;
}
if (w < 0 || h < 0)
return true;
if (h != 0 && (w > max / h))
return true;
return false;
}
void check_head_error(struct hevc_state_s *hevc)
{
#define pcm_enabled_flag 0x040
#define pcm_sample_bit_depth_luma 0x041
#define pcm_sample_bit_depth_chroma 0x042
hevc->head_error_flag = 0;
if ((error_handle_policy & 0x40) == 0)
return;
if (get_lmem_params(hevc, pcm_enabled_flag)) {
uint16_t pcm_depth_luma = get_lmem_params(
hevc, pcm_sample_bit_depth_luma);
uint16_t pcm_sample_chroma = get_lmem_params(
hevc, pcm_sample_bit_depth_chroma);
if (pcm_depth_luma >
hevc->bit_depth_luma ||
pcm_sample_chroma >
hevc->bit_depth_chroma) {
hevc_print(hevc, 0,
"error, pcm bit depth %d, %d is greater than normal bit depth %d, %d\n",
pcm_depth_luma,
pcm_sample_chroma,
hevc->bit_depth_luma,
hevc->bit_depth_chroma);
hevc->head_error_flag = 1;
}
}
}
#endif
#ifdef SUPPORT_10BIT
/* Losless compression body buffer size 4K per 64x32 (jt) */
static int compute_losless_comp_body_size(struct hevc_state_s *hevc,
int width, int height, int mem_saving_mode)
{
int width_x64;
int height_x32;
int bsize;
width_x64 = width + 63;
width_x64 >>= 6;
height_x32 = height + 31;
height_x32 >>= 5;
if (mem_saving_mode == 1 && hevc->mmu_enable)
bsize = 3200 * width_x64 * height_x32;
else if (mem_saving_mode == 1)
bsize = 3072 * width_x64 * height_x32;
else
bsize = 4096 * width_x64 * height_x32;
return bsize;
}
/* Losless compression header buffer size 32bytes per 128x64 (jt) */
static int compute_losless_comp_header_size(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;
return hsize;
}
#endif
static int add_log(struct hevc_state_s *hevc,
const char *fmt, ...)
{
#define HEVC_LOG_BUF 196
struct debug_log_s *log_item;
unsigned char buf[HEVC_LOG_BUF];
int len = 0;
va_list args;
mutex_lock(&vh265_log_mutex);
va_start(args, fmt);
len = sprintf(buf, "<%ld> <%05d> ",
jiffies, hevc->decode_idx);
len += vsnprintf(buf + len,
HEVC_LOG_BUF - len, fmt, args);
va_end(args);
log_item = kmalloc(
sizeof(struct debug_log_s) + len,
GFP_KERNEL);
if (log_item) {
INIT_LIST_HEAD(&log_item->list);
strcpy(&log_item->data, buf);
list_add_tail(&log_item->list,
&hevc->log_list);
}
mutex_unlock(&vh265_log_mutex);
return 0;
}
static void dump_log(struct hevc_state_s *hevc)
{
int i = 0;
struct debug_log_s *log_item, *tmp;
mutex_lock(&vh265_log_mutex);
list_for_each_entry_safe(log_item, tmp, &hevc->log_list, list) {
hevc_print(hevc, 0,
"[LOG%04d]%s\n",
i++,
&log_item->data);
list_del(&log_item->list);
kfree(log_item);
}
mutex_unlock(&vh265_log_mutex);
}
static unsigned char is_skip_decoding(struct hevc_state_s *hevc,
struct PIC_s *pic)
{
if (pic->error_mark
&& ((hevc->ignore_bufmgr_error & 0x1) == 0))
return 1;
return 0;
}
static int get_pic_poc(struct hevc_state_s *hevc,
unsigned int idx)
{
if (idx != 0xff
&& idx < MAX_REF_PIC_NUM
&& hevc->m_PIC[idx])
return hevc->m_PIC[idx]->POC;
return INVALID_POC;
}
#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
static int get_valid_double_write_mode(struct hevc_state_s *hevc)
{
return (hevc->m_ins_flag &&
((double_write_mode & 0x80000000) == 0)) ?
hevc->double_write_mode :
(double_write_mode & 0x7fffffff);
}
static int get_dynamic_buf_num_margin(struct hevc_state_s *hevc)
{
return (hevc->m_ins_flag &&
((dynamic_buf_num_margin & 0x80000000) == 0)) ?
hevc->dynamic_buf_num_margin :
(dynamic_buf_num_margin & 0x7fffffff);
}
#endif
static int get_double_write_mode(struct hevc_state_s *hevc)
{
u32 valid_dw_mode = get_valid_double_write_mode(hevc);
int w = hevc->pic_w;
int h = hevc->pic_h;
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 int v4l_parser_get_double_write_mode(struct hevc_state_s *hevc, int w, int h)
{
u32 valid_dw_mode = get_valid_double_write_mode(hevc);
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;
case 0x1000:
if (w * h > 1920 * 1080)
dw = 3;
else if (w * h > 960 * 540)
dw = 5;
else
dw = 1;
break;
default:
dw = valid_dw_mode;
break;
}
return dw;
}
static int get_double_write_ratio(struct hevc_state_s *hevc,
int dw_mode)
{
int ratio = 1;
if ((dw_mode == 2) ||
(dw_mode == 3))
ratio = 4;
else if ((dw_mode == 4) ||
(dw_mode == 5))
ratio = 2;
return ratio;
}
#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
static unsigned char get_idx(struct hevc_state_s *hevc)
{
return hevc->index;
}
#endif
#undef pr_info
#define pr_info printk
static int hevc_print(struct hevc_state_s *hevc,
int flag, const char *fmt, ...)
{
#define HEVC_PRINT_BUF 256
unsigned char buf[HEVC_PRINT_BUF];
int len = 0;
#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
if (hevc == NULL ||
(flag == 0) ||
((debug_mask &
(1 << hevc->index))
&& (debug & flag))) {
#endif
va_list args;
va_start(args, fmt);
if (hevc)
len = sprintf(buf, "[%d]", hevc->index);
vsnprintf(buf + len, HEVC_PRINT_BUF - len, fmt, args);
pr_debug("%s", buf);
va_end(args);
#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
}
#endif
return 0;
}
static int hevc_print_cont(struct hevc_state_s *hevc,
int flag, const char *fmt, ...)
{
unsigned char buf[HEVC_PRINT_BUF];
int len = 0;
#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
if (hevc == NULL ||
(flag == 0) ||
((debug_mask &
(1 << hevc->index))
&& (debug & flag))) {
#endif
va_list args;
va_start(args, fmt);
vsnprintf(buf + len, HEVC_PRINT_BUF - len, fmt, args);
pr_info("%s", buf);
va_end(args);
#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
}
#endif
return 0;
}
static void put_mv_buf(struct hevc_state_s *hevc,
struct PIC_s *pic);
static void update_vf_memhandle(struct hevc_state_s *hevc,
struct vframe_s *vf, struct PIC_s *pic);
static void set_canvas(struct hevc_state_s *hevc, struct PIC_s *pic);
static void release_aux_data(struct hevc_state_s *hevc,
struct PIC_s *pic);
static void release_pic_mmu_buf(struct hevc_state_s *hevc, struct PIC_s *pic);
#ifdef MULTI_INSTANCE_SUPPORT
static void backup_decode_state(struct hevc_state_s *hevc)
{
hevc->m_pocRandomAccess_bak = hevc->m_pocRandomAccess;
hevc->curr_POC_bak = hevc->curr_POC;
hevc->iPrevPOC_bak = hevc->iPrevPOC;
hevc->iPrevTid0POC_bak = hevc->iPrevTid0POC;
hevc->start_parser_type_bak = hevc->start_parser_type;
hevc->start_decoding_flag_bak = hevc->start_decoding_flag;
hevc->rps_set_id_bak = hevc->rps_set_id;
hevc->pic_decoded_lcu_idx_bak = hevc->pic_decoded_lcu_idx;
hevc->decode_idx_bak = hevc->decode_idx;
}
static void restore_decode_state(struct hevc_state_s *hevc)
{
struct vdec_s *vdec = hw_to_vdec(hevc);
if (!vdec_has_more_input(vdec)) {
hevc->pic_decoded_lcu_idx =
READ_VREG(HEVC_PARSER_LCU_START)
& 0xffffff;
return;
}
hevc_print(hevc, PRINT_FLAG_VDEC_STATUS,
"%s: discard pic index 0x%x\n",
__func__, hevc->decoding_pic ?
hevc->decoding_pic->index : 0xff);
if (hevc->decoding_pic) {
hevc->decoding_pic->error_mark = 0;
hevc->decoding_pic->output_ready = 0;
hevc->decoding_pic->show_frame = false;
hevc->decoding_pic->output_mark = 0;
hevc->decoding_pic->referenced = 0;
hevc->decoding_pic->POC = INVALID_POC;
put_mv_buf(hevc, hevc->decoding_pic);
release_aux_data(hevc, hevc->decoding_pic);
hevc->decoding_pic = NULL;
}
if (vdec_stream_based(vdec) &&
(hevc->decode_idx - hevc->decode_idx_bak > 1)) {
int i;
hevc_print(hevc, 0, "decode_idx %d, decode_idx_bak %d\n",
hevc->decode_idx, hevc->decode_idx_bak);
for (i = 0; i < MAX_REF_PIC_NUM; i++) {
struct PIC_s *pic;
pic = hevc->m_PIC[i];
if (pic == NULL ||
(pic->index == -1) ||
(pic->BUF_index == -1) ||
(pic->POC == INVALID_POC))
continue;
if ((pic->decode_idx >= hevc->decode_idx_bak) &&
pic->decode_idx != (hevc->decode_idx - 1)) {
hevc_print(hevc, 0, "release error buffer\n");
pic->error_mark = 0;
pic->output_ready = 0;
pic->show_frame = false;
pic->output_mark = 0;
pic->referenced = 0;
pic->POC = INVALID_POC;
put_mv_buf(hevc, pic);
release_aux_data(hevc, pic);
}
}
}
hevc->decode_idx = hevc->decode_idx_bak;
hevc->m_pocRandomAccess = hevc->m_pocRandomAccess_bak;
hevc->curr_POC = hevc->curr_POC_bak;
hevc->iPrevPOC = hevc->iPrevPOC_bak;
hevc->iPrevTid0POC = hevc->iPrevTid0POC_bak;
hevc->start_parser_type = hevc->start_parser_type_bak;
hevc->start_decoding_flag = hevc->start_decoding_flag_bak;
hevc->rps_set_id = hevc->rps_set_id_bak;
hevc->pic_decoded_lcu_idx = hevc->pic_decoded_lcu_idx_bak;
if (hevc->pic_list_init_flag == 1)
hevc->pic_list_init_flag = 0;
/*if (hevc->decode_idx == 0)
hevc->start_decoding_flag = 0;*/
hevc->slice_idx = 0;
hevc->used_4k_num = -1;
}
#endif
static void hevc_init_stru(struct hevc_state_s *hevc,
struct BuffInfo_s *buf_spec_i)
{
int i;
INIT_LIST_HEAD(&hevc->log_list);
hevc->work_space_buf = buf_spec_i;
hevc->prefix_aux_size = 0;
hevc->suffix_aux_size = 0;
hevc->aux_addr = NULL;
hevc->rpm_addr = NULL;
hevc->lmem_addr = NULL;
hevc->curr_POC = INVALID_POC;
hevc->pic_list_init_flag = 0;
hevc->use_cma_flag = 0;
hevc->decode_idx = 0;
hevc->slice_idx = 0;
hevc->new_pic = 0;
hevc->new_tile = 0;
hevc->iPrevPOC = 0;
hevc->list_no = 0;
/* int m_uiMaxCUWidth = 1<<7; */
/* int m_uiMaxCUHeight = 1<<7; */
hevc->m_pocRandomAccess = MAX_INT;
hevc->tile_enabled = 0;
hevc->tile_x = 0;
hevc->tile_y = 0;
hevc->iPrevTid0POC = 0;
hevc->slice_addr = 0;
hevc->slice_segment_addr = 0;
hevc->skip_flag = 0;
hevc->misc_flag0 = 0;
hevc->cur_pic = NULL;
hevc->col_pic = NULL;
hevc->wait_buf = 0;
hevc->error_flag = 0;
hevc->head_error_flag = 0;
hevc->error_skip_nal_count = 0;
hevc->have_vps = 0;
hevc->have_sps = 0;
hevc->have_pps = 0;
hevc->have_valid_start_slice = 0;
hevc->pts_mode = PTS_NORMAL;
hevc->last_pts = 0;
hevc->last_lookup_pts = 0;
hevc->last_pts_us64 = 0;
hevc->last_lookup_pts_us64 = 0;
hevc->pts_mode_switching_count = 0;
hevc->pts_mode_recovery_count = 0;
hevc->PB_skip_mode = nal_skip_policy & 0x3;
hevc->PB_skip_count_after_decoding = (nal_skip_policy >> 16) & 0xffff;
if (hevc->PB_skip_mode == 0)
hevc->ignore_bufmgr_error = 0x1;
else
hevc->ignore_bufmgr_error = 0x0;
if (hevc->is_used_v4l) {
for (i = 0; i < MAX_REF_PIC_NUM; i++) {
if (hevc->m_PIC[i] != NULL) {
memset(hevc->m_PIC[i], 0 ,sizeof(struct PIC_s));
hevc->m_PIC[i]->index = i;
}
}
}
hevc->pic_num = 0;
hevc->lcu_x_num_pre = 0;
hevc->lcu_y_num_pre = 0;
hevc->first_pic_after_recover = 0;
hevc->pre_top_pic = NULL;
hevc->pre_bot_pic = NULL;
hevc->sei_present_flag = 0;
hevc->valve_count = 0;
hevc->first_pic_flag = 0;
#ifdef MULTI_INSTANCE_SUPPORT
hevc->decoded_poc = INVALID_POC;
hevc->start_process_time = 0;
hevc->last_lcu_idx = 0;
hevc->decode_timeout_count = 0;
hevc->timeout_num = 0;
hevc->eos = 0;
hevc->pic_decoded_lcu_idx = -1;
hevc->over_decode = 0;
hevc->used_4k_num = -1;
hevc->start_decoding_flag = 0;
hevc->rps_set_id = 0;
backup_decode_state(hevc);
#endif
#ifdef DETREFILL_ENABLE
hevc->detbuf_adr = 0;
hevc->detbuf_adr_virt = NULL;
#endif
}
static int post_picture_early(struct vdec_s *vdec, int index);
static int prepare_display_buf(struct vdec_s *vdec, struct PIC_s *pic);
static int H265_alloc_mmu(struct hevc_state_s *hevc,
struct PIC_s *new_pic, unsigned short bit_depth,
unsigned int *mmu_index_adr);
#ifdef DETREFILL_ENABLE
#define DETREFILL_BUF_SIZE (4 * 0x4000)
#define HEVC_SAO_DBG_MODE0 0x361e
#define HEVC_SAO_DBG_MODE1 0x361f
#define HEVC_SAO_CTRL10 0x362e
#define HEVC_SAO_CTRL11 0x362f
static int init_detrefill_buf(struct hevc_state_s *hevc)
{
if (hevc->detbuf_adr_virt)
return 0;
hevc->detbuf_adr_virt =
(void *)dma_alloc_coherent(amports_get_dma_device(),
DETREFILL_BUF_SIZE, &hevc->detbuf_adr,
GFP_KERNEL);
if (hevc->detbuf_adr_virt == NULL) {
pr_err("%s: failed to alloc ETREFILL_BUF\n", __func__);
return -1;
}
return 0;
}
static void uninit_detrefill_buf(struct hevc_state_s *hevc)
{
if (hevc->detbuf_adr_virt) {
dma_free_coherent(amports_get_dma_device(),
DETREFILL_BUF_SIZE, hevc->detbuf_adr_virt,
hevc->detbuf_adr);
hevc->detbuf_adr_virt = NULL;
hevc->detbuf_adr = 0;
}
}
/*
* convert uncompressed frame buffer data from/to ddr
*/
static void convUnc8x4blk(uint16_t* blk8x4Luma,
uint16_t* blk8x4Cb, uint16_t* blk8x4Cr, uint16_t* cmBodyBuf, int32_t direction)
{
if (direction == 0) {
blk8x4Luma[3 + 0 * 8] = ((cmBodyBuf[0] >> 0)) & 0x3ff;
blk8x4Luma[3 + 1 * 8] = ((cmBodyBuf[1] << 6)
| (cmBodyBuf[0] >> 10)) & 0x3ff;
blk8x4Luma[3 + 2 * 8] = ((cmBodyBuf[1] >> 4)) & 0x3ff;
blk8x4Luma[3 + 3 * 8] = ((cmBodyBuf[2] << 2)
| (cmBodyBuf[1] >> 14)) & 0x3ff;
blk8x4Luma[7 + 0 * 8] = ((cmBodyBuf[3] << 8)
| (cmBodyBuf[2] >> 8)) & 0x3ff;
blk8x4Luma[7 + 1 * 8] = ((cmBodyBuf[3] >> 2)) & 0x3ff;
blk8x4Luma[7 + 2 * 8] = ((cmBodyBuf[4] << 4)
| (cmBodyBuf[3] >> 12)) & 0x3ff;
blk8x4Luma[7 + 3 * 8] = ((cmBodyBuf[4] >> 6)) & 0x3ff;
blk8x4Cb [0 + 0 * 4] = ((cmBodyBuf[5] >> 0)) & 0x3ff;
blk8x4Cr [0 + 0 * 4] = ((cmBodyBuf[6] << 6)
| (cmBodyBuf[5] >> 10)) & 0x3ff;
blk8x4Cb [0 + 1 * 4] = ((cmBodyBuf[6] >> 4)) & 0x3ff;
blk8x4Cr [0 + 1 * 4] = ((cmBodyBuf[7] << 2)
| (cmBodyBuf[6] >> 14)) & 0x3ff;
blk8x4Luma[0 + 0 * 8] = ((cmBodyBuf[0 + 8] >> 0)) & 0x3ff;
blk8x4Luma[1 + 0 * 8] = ((cmBodyBuf[1 + 8] << 6) |
(cmBodyBuf[0 + 8] >> 10)) & 0x3ff;
blk8x4Luma[2 + 0 * 8] = ((cmBodyBuf[1 + 8] >> 4)) & 0x3ff;
blk8x4Luma[0 + 1 * 8] = ((cmBodyBuf[2 + 8] << 2) |
(cmBodyBuf[1 + 8] >> 14)) & 0x3ff;
blk8x4Luma[1 + 1 * 8] = ((cmBodyBuf[3 + 8] << 8) |
(cmBodyBuf[2 + 8] >> 8)) & 0x3ff;
blk8x4Luma[2 + 1 * 8] = ((cmBodyBuf[3 + 8] >> 2)) & 0x3ff;
blk8x4Luma[0 + 2 * 8] = ((cmBodyBuf[4 + 8] << 4) |
(cmBodyBuf[3 + 8] >> 12)) & 0x3ff;
blk8x4Luma[1 + 2 * 8] = ((cmBodyBuf[4 + 8] >> 6)) & 0x3ff;
blk8x4Luma[2 + 2 * 8] = ((cmBodyBuf[5 + 8] >> 0)) & 0x3ff;
blk8x4Luma[0 + 3 * 8] = ((cmBodyBuf[6 + 8] << 6) |
(cmBodyBuf[5 + 8] >> 10)) & 0x3ff;
blk8x4Luma[1 + 3 * 8] = ((cmBodyBuf[6 + 8] >> 4)) & 0x3ff;
blk8x4Luma[2 + 3 * 8] = ((cmBodyBuf[7 + 8] << 2) |
(cmBodyBuf[6 + 8] >> 14)) & 0x3ff;
blk8x4Luma[4 + 0 * 8] = ((cmBodyBuf[0 + 16] >> 0)) & 0x3ff;
blk8x4Luma[5 + 0 * 8] = ((cmBodyBuf[1 + 16] << 6) |
(cmBodyBuf[0 + 16] >> 10)) & 0x3ff;
blk8x4Luma[6 + 0 * 8] = ((cmBodyBuf[1 + 16] >> 4)) & 0x3ff;
blk8x4Luma[4 + 1 * 8] = ((cmBodyBuf[2 + 16] << 2) |
(cmBodyBuf[1 + 16] >> 14)) & 0x3ff;
blk8x4Luma[5 + 1 * 8] = ((cmBodyBuf[3 + 16] << 8) |
(cmBodyBuf[2 + 16] >> 8)) & 0x3ff;
blk8x4Luma[6 + 1 * 8] = ((cmBodyBuf[3 + 16] >> 2)) & 0x3ff;
blk8x4Luma[4 + 2 * 8] = ((cmBodyBuf[4 + 16] << 4) |
(cmBodyBuf[3 + 16] >> 12)) & 0x3ff;
blk8x4Luma[5 + 2 * 8] = ((cmBodyBuf[4 + 16] >> 6)) & 0x3ff;
blk8x4Luma[6 + 2 * 8] = ((cmBodyBuf[5 + 16] >> 0)) & 0x3ff;
blk8x4Luma[4 + 3 * 8] = ((cmBodyBuf[6 + 16] << 6) |
(cmBodyBuf[5 + 16] >> 10)) & 0x3ff;
blk8x4Luma[5 + 3 * 8] = ((cmBodyBuf[6 + 16] >> 4)) & 0x3ff;
blk8x4Luma[6 + 3 * 8] = ((cmBodyBuf[7 + 16] << 2) |
(cmBodyBuf[6 + 16] >> 14)) & 0x3ff;
blk8x4Cb[1 + 0 * 4] = ((cmBodyBuf[0 + 24] >> 0)) & 0x3ff;
blk8x4Cr[1 + 0 * 4] = ((cmBodyBuf[1 + 24] << 6) |
(cmBodyBuf[0 + 24] >> 10)) & 0x3ff;
blk8x4Cb[2 + 0 * 4] = ((cmBodyBuf[1 + 24] >> 4)) & 0x3ff;
blk8x4Cr[2 + 0 * 4] = ((cmBodyBuf[2 + 24] << 2) |
(cmBodyBuf[1 + 24] >> 14)) & 0x3ff;
blk8x4Cb[3 + 0 * 4] = ((cmBodyBuf[3 + 24] << 8) |
(cmBodyBuf[2 + 24] >> 8)) & 0x3ff;
blk8x4Cr[3 + 0 * 4] = ((cmBodyBuf[3 + 24] >> 2)) & 0x3ff;
blk8x4Cb[1 + 1 * 4] = ((cmBodyBuf[4 + 24] << 4) |
(cmBodyBuf[3 + 24] >> 12)) & 0x3ff;
blk8x4Cr[1 + 1 * 4] = ((cmBodyBuf[4 + 24] >> 6)) & 0x3ff;
blk8x4Cb[2 + 1 * 4] = ((cmBodyBuf[5 + 24] >> 0)) & 0x3ff;
blk8x4Cr[2 + 1 * 4] = ((cmBodyBuf[6 + 24] << 6) |
(cmBodyBuf[5 + 24] >> 10)) & 0x3ff;
blk8x4Cb[3 + 1 * 4] = ((cmBodyBuf[6 + 24] >> 4)) & 0x3ff;
blk8x4Cr[3 + 1 * 4] = ((cmBodyBuf[7 + 24] << 2) |
(cmBodyBuf[6 + 24] >> 14)) & 0x3ff;
} else {
cmBodyBuf[0 + 8 * 0] = (blk8x4Luma[3 + 1 * 8] << 10) |
blk8x4Luma[3 + 0 * 8];
cmBodyBuf[1 + 8 * 0] = (blk8x4Luma[3 + 3 * 8] << 14) |
(blk8x4Luma[3 + 2 * 8] << 4) | (blk8x4Luma[3 + 1 * 8] >> 6);
cmBodyBuf[2 + 8 * 0] = (blk8x4Luma[7 + 0 * 8] << 8) |
(blk8x4Luma[3 + 3 * 8] >> 2);
cmBodyBuf[3 + 8 * 0] = (blk8x4Luma[7 + 2 * 8] << 12) |
(blk8x4Luma[7 + 1 * 8] << 2) | (blk8x4Luma[7 + 0 * 8] >>8);
cmBodyBuf[4 + 8 * 0] = (blk8x4Luma[7 + 3 * 8] << 6) |
(blk8x4Luma[7 + 2 * 8] >>4);
cmBodyBuf[5 + 8 * 0] = (blk8x4Cr[0 + 0 * 4] << 10) |
blk8x4Cb[0 + 0 * 4];
cmBodyBuf[6 + 8 * 0] = (blk8x4Cr[0 + 1 * 4] << 14) |
(blk8x4Cb[0 + 1 * 4] << 4) | (blk8x4Cr[0 + 0 * 4] >> 6);
cmBodyBuf[7 + 8 * 0] = (0<< 8) | (blk8x4Cr[0 + 1 * 4] >> 2);
cmBodyBuf[0 + 8 * 1] = (blk8x4Luma[1 + 0 * 8] << 10) |
blk8x4Luma[0 + 0 * 8];
cmBodyBuf[1 + 8 * 1] = (blk8x4Luma[0 + 1 * 8] << 14) |
(blk8x4Luma[2 + 0 * 8] << 4) | (blk8x4Luma[1 + 0 * 8] >> 6);
cmBodyBuf[2 + 8 * 1] = (blk8x4Luma[1 + 1 * 8] << 8) |
(blk8x4Luma[0 + 1 * 8] >> 2);
cmBodyBuf[3 + 8 * 1] = (blk8x4Luma[0 + 2 * 8] << 12) |
(blk8x4Luma[2 + 1 * 8] << 2) | (blk8x4Luma[1 + 1 * 8] >>8);
cmBodyBuf[4 + 8 * 1] = (blk8x4Luma[1 + 2 * 8] << 6) |
(blk8x4Luma[0 + 2 * 8] >>4);
cmBodyBuf[5 + 8 * 1] = (blk8x4Luma[0 + 3 * 8] << 10) |
blk8x4Luma[2 + 2 * 8];
cmBodyBuf[6 + 8 * 1] = (blk8x4Luma[2 + 3 * 8] << 14) |
(blk8x4Luma[1 + 3 * 8] << 4) | (blk8x4Luma[0 + 3 * 8] >> 6);
cmBodyBuf[7 + 8 * 1] = (0<< 8) | (blk8x4Luma[2 + 3 * 8] >> 2);
cmBodyBuf[0 + 8 * 2] = (blk8x4Luma[5 + 0 * 8] << 10) |
blk8x4Luma[4 + 0 * 8];
cmBodyBuf[1 + 8 * 2] = (blk8x4Luma[4 + 1 * 8] << 14) |
(blk8x4Luma[6 + 0 * 8] << 4) | (blk8x4Luma[5 + 0 * 8] >> 6);
cmBodyBuf[2 + 8 * 2] = (blk8x4Luma[5 + 1 * 8] << 8) |
(blk8x4Luma[4 + 1 * 8] >> 2);
cmBodyBuf[3 + 8 * 2] = (blk8x4Luma[4 + 2 * 8] << 12) |
(blk8x4Luma[6 + 1 * 8] << 2) | (blk8x4Luma[5 + 1 * 8] >>8);
cmBodyBuf[4 + 8 * 2] = (blk8x4Luma[5 + 2 * 8] << 6) |
(blk8x4Luma[4 + 2 * 8] >>4);
cmBodyBuf[5 + 8 * 2] = (blk8x4Luma[4 + 3 * 8] << 10) |
blk8x4Luma[6 + 2 * 8];
cmBodyBuf[6 + 8 * 2] = (blk8x4Luma[6 + 3 * 8] << 14) |
(blk8x4Luma[5 + 3 * 8] << 4) | (blk8x4Luma[4 + 3 * 8] >> 6);
cmBodyBuf[7 + 8 * 2] = (0<< 8) | (blk8x4Luma[6 + 3 * 8] >> 2);
cmBodyBuf[0 + 8 * 3] = (blk8x4Cr[1 + 0 * 4] << 10) |
blk8x4Cb[1 + 0 * 4];
cmBodyBuf[1 + 8 * 3] = (blk8x4Cr[2 + 0 * 4] << 14) |
(blk8x4Cb[2 + 0 * 4] << 4) | (blk8x4Cr[1 + 0 * 4] >> 6);
cmBodyBuf[2 + 8 * 3] = (blk8x4Cb[3 + 0 * 4] << 8) |
(blk8x4Cr[2 + 0 * 4] >> 2);
cmBodyBuf[3 + 8 * 3] = (blk8x4Cb[1 + 1 * 4] << 12) |
(blk8x4Cr[3 + 0 * 4] << 2) | (blk8x4Cb[3 + 0 * 4] >>8);
cmBodyBuf[4 + 8 * 3] = (blk8x4Cr[1 + 1 * 4] << 6) |
(blk8x4Cb[1 + 1 * 4] >>4);
cmBodyBuf[5 + 8 * 3] = (blk8x4Cr[2 + 1 * 4] << 10) |
blk8x4Cb[2 + 1 * 4];
cmBodyBuf[6 + 8 * 3] = (blk8x4Cr[3 + 1 * 4] << 14) |
(blk8x4Cb[3 + 1 * 4] << 4) | (blk8x4Cr[2 + 1 * 4] >> 6);
cmBodyBuf[7 + 8 * 3] = (0 << 8) | (blk8x4Cr[3 + 1 * 4] >> 2);
}
}
static void corrRefillWithAmrisc (
struct hevc_state_s *hevc,
uint32_t cmHeaderBaseAddr,
uint32_t picWidth,
uint32_t ctuPosition)
{
int32_t i;
uint16_t ctux = (ctuPosition>>16) & 0xffff;
uint16_t ctuy = (ctuPosition>> 0) & 0xffff;
int32_t aboveCtuAvailable = (ctuy) ? 1 : 0;
uint16_t cmBodyBuf[32 * 18];
uint32_t pic_width_x64_pre = picWidth + 0x3f;
uint32_t pic_width_x64 = pic_width_x64_pre >> 6;
uint32_t stride64x64 = pic_width_x64 * 128;
uint32_t addr_offset64x64_abv = stride64x64 *
(aboveCtuAvailable ? ctuy - 1 : ctuy) + 128 * ctux;
uint32_t addr_offset64x64_cur = stride64x64*ctuy + 128 * ctux;
uint32_t cmHeaderAddrAbv = cmHeaderBaseAddr + addr_offset64x64_abv;
uint32_t cmHeaderAddrCur = cmHeaderBaseAddr + addr_offset64x64_cur;
unsigned int tmpData32;
uint16_t blkBuf0Y[32];
uint16_t blkBuf0Cb[8];
uint16_t blkBuf0Cr[8];
uint16_t blkBuf1Y[32];
uint16_t blkBuf1Cb[8];
uint16_t blkBuf1Cr[8];
int32_t blkBufCnt = 0;
int32_t blkIdx;
WRITE_VREG(HEVC_SAO_CTRL10, cmHeaderAddrAbv);
WRITE_VREG(HEVC_SAO_CTRL11, cmHeaderAddrCur);
WRITE_VREG(HEVC_SAO_DBG_MODE0, hevc->detbuf_adr);
WRITE_VREG(HEVC_SAO_DBG_MODE1, 2);
for (i = 0; i < 32 * 18; i++)
cmBodyBuf[i] = 0;
hevc_print(hevc, H265_DEBUG_BUFMGR_MORE,
"%s, %d\n", __func__, __LINE__);
do {
tmpData32 = READ_VREG(HEVC_SAO_DBG_MODE1);
} while (tmpData32);
hevc_print(hevc, H265_DEBUG_BUFMGR_MORE,
"%s, %d\n", __func__, __LINE__);
hevc_print(hevc, H265_DEBUG_DETAIL,
"cmBodyBuf from detbuf:\n");
for (i = 0; i < 32 * 18; i++) {
cmBodyBuf[i] = hevc->detbuf_adr_virt[i];
if (get_dbg_flag(hevc) &
H265_DEBUG_DETAIL) {
if ((i & 0xf) == 0)
hevc_print_cont(hevc, 0, "\n");
hevc_print_cont(hevc, 0, "%02x ", cmBodyBuf[i]);
}
}
hevc_print_cont(hevc, H265_DEBUG_DETAIL, "\n");
for (i = 0; i < 32; i++)
blkBuf0Y[i] = 0;
for (i = 0; i < 8; i++)
blkBuf0Cb[i] = 0;
for (i = 0; i < 8; i++)
blkBuf0Cr[i] = 0;
for (i = 0; i < 32; i++)
blkBuf1Y[i] = 0;
for (i = 0; i < 8; i++)
blkBuf1Cb[i] = 0;
for (i = 0; i < 8; i++)
blkBuf1Cr[i] = 0;
for (blkIdx = 0; blkIdx < 18; blkIdx++) {
int32_t inAboveCtu = (blkIdx<2) ? 1 : 0;
int32_t restoreEnable = (blkIdx>0) ? 1 : 0;
uint16_t* blkY = (blkBufCnt==0) ? blkBuf0Y : blkBuf1Y ;
uint16_t* blkCb = (blkBufCnt==0) ? blkBuf0Cb : blkBuf1Cb;
uint16_t* blkCr = (blkBufCnt==0) ? blkBuf0Cr : blkBuf1Cr;
uint16_t* cmBodyBufNow = cmBodyBuf + (blkIdx * 32);
if (!aboveCtuAvailable && inAboveCtu)
continue;
/* detRefillBuf --> 8x4block*/
convUnc8x4blk(blkY, blkCb, blkCr, cmBodyBufNow, 0);
if (restoreEnable) {
blkY[3 + 0 * 8] = blkY[2 + 0 * 8] + 2;
blkY[4 + 0 * 8] = blkY[1 + 0 * 8] + 3;
blkY[5 + 0 * 8] = blkY[0 + 0 * 8] + 1;
blkY[6 + 0 * 8] = blkY[0 + 0 * 8] + 2;
blkY[7 + 0 * 8] = blkY[1 + 0 * 8] + 2;
blkY[3 + 1 * 8] = blkY[2 + 1 * 8] + 1;
blkY[4 + 1 * 8] = blkY[1 + 1 * 8] + 2;
blkY[5 + 1 * 8] = blkY[0 + 1 * 8] + 2;
blkY[6 + 1 * 8] = blkY[0 + 1 * 8] + 2;
blkY[7 + 1 * 8] = blkY[1 + 1 * 8] + 3;
blkY[3 + 2 * 8] = blkY[2 + 2 * 8] + 3;
blkY[4 + 2 * 8] = blkY[1 + 2 * 8] + 1;
blkY[5 + 2 * 8] = blkY[0 + 2 * 8] + 3;
blkY[6 + 2 * 8] = blkY[0 + 2 * 8] + 3;
blkY[7 + 2 * 8] = blkY[1 + 2 * 8] + 3;
blkY[3 + 3 * 8] = blkY[2 + 3 * 8] + 0;
blkY[4 + 3 * 8] = blkY[1 + 3 * 8] + 0;
blkY[5 + 3 * 8] = blkY[0 + 3 * 8] + 1;
blkY[6 + 3 * 8] = blkY[0 + 3 * 8] + 2;
blkY[7 + 3 * 8] = blkY[1 + 3 * 8] + 1;
blkCb[1 + 0 * 4] = blkCb[0 + 0 * 4];
blkCb[2 + 0 * 4] = blkCb[0 + 0 * 4];
blkCb[3 + 0 * 4] = blkCb[0 + 0 * 4];
blkCb[1 + 1 * 4] = blkCb[0 + 1 * 4];
blkCb[2 + 1 * 4] = blkCb[0 + 1 * 4];
blkCb[3 + 1 * 4] = blkCb[0 + 1 * 4];
blkCr[1 + 0 * 4] = blkCr[0 + 0 * 4];
blkCr[2 + 0 * 4] = blkCr[0 + 0 * 4];
blkCr[3 + 0 * 4] = blkCr[0 + 0 * 4];
blkCr[1 + 1 * 4] = blkCr[0 + 1 * 4];
blkCr[2 + 1 * 4] = blkCr[0 + 1 * 4];
blkCr[3 + 1 * 4] = blkCr[0 + 1 * 4];
/*Store data back to DDR*/
convUnc8x4blk(blkY, blkCb, blkCr, cmBodyBufNow, 1);
}
blkBufCnt = (blkBufCnt==1) ? 0 : blkBufCnt + 1;
}
hevc_print(hevc, H265_DEBUG_DETAIL,
"cmBodyBuf to detbuf:\n");
for (i = 0; i < 32 * 18; i++) {
hevc->detbuf_adr_virt[i] = cmBodyBuf[i];
if (get_dbg_flag(hevc) &
H265_DEBUG_DETAIL) {
if ((i & 0xf) == 0)
hevc_print_cont(hevc, 0, "\n");
hevc_print_cont(hevc, 0, "%02x ", cmBodyBuf[i]);
}
}
hevc_print_cont(hevc, H265_DEBUG_DETAIL, "\n");
WRITE_VREG(HEVC_SAO_DBG_MODE1, 3);
hevc_print(hevc, H265_DEBUG_BUFMGR_MORE,
"%s, %d\n", __func__, __LINE__);
do {
tmpData32 = READ_VREG(HEVC_SAO_DBG_MODE1);
} while (tmpData32);
hevc_print(hevc, H265_DEBUG_BUFMGR_MORE,
"%s, %d\n", __func__, __LINE__);
}
static void delrefill(struct hevc_state_s *hevc)
{
/*
* corrRefill
*/
/*HEVC_SAO_DBG_MODE0: picGlobalVariable
[31:30]error number
[29:20]error2([9:7]tilex[6:0]ctuy)
[19:10]error1 [9:0]error0*/
uint32_t detResult = READ_VREG(HEVC_ASSIST_SCRATCH_3);
uint32_t errorIdx;
uint32_t errorNum = (detResult>>30);
if (detResult) {
hevc_print(hevc, H265_DEBUG_BUFMGR,
"[corrRefillWithAmrisc] detResult=%08x\n", detResult);
for (errorIdx = 0; errorIdx < errorNum; errorIdx++) {
uint32_t errorPos = errorIdx * 10;
uint32_t errorResult = (detResult >> errorPos) & 0x3ff;
uint32_t tilex = (errorResult >> 7) - 1;
uint16_t ctux = hevc->m_tile[0][tilex].start_cu_x
+ hevc->m_tile[0][tilex].width - 1;
uint16_t ctuy = (uint16_t)(errorResult & 0x7f);
uint32_t ctuPosition = (ctux<< 16) + ctuy;
hevc_print(hevc, H265_DEBUG_BUFMGR,
"Idx:%d tilex:%d ctu(%d(0x%x), %d(0x%x))\n",
errorIdx,tilex,ctux,ctux, ctuy,ctuy);
corrRefillWithAmrisc(
hevc,
(uint32_t)hevc->cur_pic->header_adr,
hevc->pic_w,
ctuPosition);
}
WRITE_VREG(HEVC_ASSIST_SCRATCH_3, 0); /*clear status*/
WRITE_VREG(HEVC_SAO_DBG_MODE0, 0);
WRITE_VREG(HEVC_SAO_DBG_MODE1, 1);
}
}
#endif
static void get_rpm_param(union param_u *params)
{
int i;
unsigned int data32;
for (i = 0; i < 128; i++) {
do {
data32 = READ_VREG(RPM_CMD_REG);
/* hevc_print(hevc, 0, "%x\n", data32); */
} while ((data32 & 0x10000) == 0);
params->l.data[i] = data32 & 0xffff;
/* hevc_print(hevc, 0, "%x\n", data32); */
WRITE_VREG(RPM_CMD_REG, 0);
}
}
static int get_free_buf_idx(struct hevc_state_s *hevc)
{
int index = INVALID_IDX;
struct PIC_s *pic;
int i;
for (i = 0; i < MAX_REF_PIC_NUM; i++) {
pic = hevc->m_PIC[i];
if (pic == NULL ||
pic->index == -1 ||
pic->BUF_index == -1)
continue;
if (pic->output_mark == 0 &&
pic->referenced == 0 &&
pic->output_ready == 0 &&
pic->cma_alloc_addr) {
pic->output_ready = 1;
index = i;
break;
}
}
return index;
}
static struct PIC_s *get_pic_by_POC(struct hevc_state_s *hevc, int POC)
{
int i;
struct PIC_s *pic;
struct PIC_s *ret_pic = NULL;
if (POC == INVALID_POC)
return NULL;
for (i = 0; i < MAX_REF_PIC_NUM; i++) {
pic = hevc->m_PIC[i];
if (pic == NULL || pic->index == -1 ||
pic->BUF_index == -1)
continue;
if (pic->POC == POC) {
if (ret_pic == NULL)
ret_pic = pic;
else {
if (pic->decode_idx > ret_pic->decode_idx)
ret_pic = pic;
}
}
}
return ret_pic;
}
static struct PIC_s *get_ref_pic_by_POC(struct hevc_state_s *hevc, int POC)
{
int i;
struct PIC_s *pic;
struct PIC_s *ret_pic = NULL;
for (i = 0; i < MAX_REF_PIC_NUM; i++) {
pic = hevc->m_PIC[i];
if (pic == NULL || pic->index == -1 ||
pic->BUF_index == -1)
continue;
/*Add width and height of ref picture detection,
resolved incorrectly referenced frame.*/
if ((pic->POC == POC) && (pic->referenced) &&
(hevc->pic_w == pic->width) &&
(hevc->pic_h == pic->height)) {
if (ret_pic == NULL)
ret_pic = pic;
else {
if (pic->decode_idx > ret_pic->decode_idx)
ret_pic = pic;
}
}
}
return ret_pic;
}
static unsigned int log2i(unsigned int val)
{
unsigned int ret = -1;
while (val != 0) {
val >>= 1;
ret++;
}
return ret;
}
static int init_buf_spec(struct hevc_state_s *hevc);
static bool v4l_is_there_vframe_bound(struct hevc_state_s *hevc)
{
int i;
for (i = 0; i < MAX_REF_PIC_NUM; i++) {
struct PIC_s *pic = hevc->m_PIC[i];
if (pic && pic->vframe_bound)
return true;
}
return false;
}
static void v4l_mmu_buffer_release(struct hevc_state_s *hevc)
{
int i;
/* release workspace */
if (hevc->bmmu_box)
decoder_bmmu_box_free_idx(hevc->bmmu_box,
BMMU_WORKSPACE_ID);
/*
* it's only when vframe get back to driver, right now we can be sure
* that vframe and fd are related. if the playback exits, the capture
* requires the upper app to release when the fd is closed, and others