blob: e7ee9f5f8927d810b0f9da7f07c5857d41066887 [file] [log] [blame]
/*
* drivers/amlogic/amports/vav1.c
*
* Copyright (C) 2015 Amlogic, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*/
#define DEBUG
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/semaphore.h>
#include <linux/delay.h>
#include <linux/timer.h>
#include <linux/kfifo.h>
#include <linux/kthread.h>
#include <linux/spinlock.h>
#include <linux/platform_device.h>
#include <linux/amlogic/media/vfm/vframe.h>
#include <linux/amlogic/media/utils/amstream.h>
#include <linux/amlogic/media/utils/vformat.h>
#include <linux/amlogic/media/frame_sync/ptsserv.h>
#include <linux/amlogic/media/canvas/canvas.h>
#include <linux/amlogic/media/vfm/vframe_provider.h>
#include <linux/amlogic/media/vfm/vframe_receiver.h>
#include <linux/dma-mapping.h>
#include <linux/dma-contiguous.h>
#include <linux/slab.h>
#include <linux/amlogic/tee.h>
#include "../../../stream_input/amports/amports_priv.h"
#include <linux/amlogic/media/codec_mm/codec_mm.h>
#include "../utils/decoder_mmu_box.h"
#include "../utils/decoder_bmmu_box.h"
#include <linux/crc32.h>
#define MEM_NAME "codec_av1"
/* #include <mach/am_regs.h> */
#include <linux/amlogic/media/utils/vdec_reg.h>
#include "../utils/vdec.h"
#include "../utils/amvdec.h"
#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
#include "../utils/vdec_profile.h"
#endif
#include <linux/amlogic/media/video_sink/video.h>
#include <linux/amlogic/media/codec_mm/configs.h>
#include "../utils/config_parser.h"
#include "../utils/firmware.h"
#include "../../../common/chips/decoder_cpu_ver_info.h"
#include "../../../amvdec_ports/vdec_drv_base.h"
//#define DEBUG_UCODE_LOG
#define DEBUG_CMD
#define DEBUG_CRC_ERROR
#define SUPPORT_V4L2
//#define DEBUG_USE_VP9_DEVICE_NAME
//#define BUFMGR_ONLY_OLD_CHIP
#ifdef SUPPORT_V4L2
#include "../utils/vdec_v4l2_buffer_ops.h"
#include <media/v4l2-mem2mem.h>
#endif
#include "../../../amvdec_ports/utils/common.h"
#define AML
#include "aom_av1_define.h"
#include "av1_global.h"
#define DUMP_FILMGRAIN
#define MIX_STREAM_SUPPORT
//#define MV_USE_FIXED_BUF
//#define USE_SPEC_BUF_FOR_MMU_HEAD
#define AOM_AV1_DBLK_INIT
#define AOM_AV1_UPSCALE_INIT
#define USE_DEC_PIC_END
#include "vav1.h"
#define FGS_TABLE_SIZE (512 * 128 / 8)
#define AV1_GMC_PARAM_BUFF_ADDR 0x316d
#define HEVCD_MPP_DECOMP_AXIURG_CTL 0x34c7
#define HEVC_FGS_IDX 0x3660
#define HEVC_FGS_DATA 0x3661
#define HEVC_FGS_CTRL 0x3662
#define AV1_SKIP_MODE_INFO 0x316c
#define AV1_QUANT_WR 0x3146
#define AV1_SEG_W_ADDR 0x3165
#define AV1_SEG_R_ADDR 0x3166
#define AV1_REF_SEG_INFO 0x3171
#define HEVC_ASSIST_PIC_SIZE_FB_READ 0x300d
#define PARSER_REF_SCALE_ENBL 0x316b
#define HEVC_MPRED_MV_RPTR_1 0x3263
#define HEVC_MPRED_MV_RPTR_2 0x3264
#define HEVC_SAO_CTRL9 0x362d
#define HEVC_FGS_TABLE_START 0x3666
#define HEVC_FGS_TABLE_LENGTH 0x3667
#define HEVC_DBLK_CDEF0 0x3515
#define HEVC_DBLK_CDEF1 0x3516
#define HEVC_DBLK_UPS1 0x351c
#define HEVC_DBLK_UPS2 0x351d
#define HEVC_DBLK_UPS3 0x351e
#define HEVC_DBLK_UPS4 0x351f
#define HEVC_DBLK_UPS5 0x3520
#define AV1_UPSCALE_X0_QN 0x316e
#define AV1_UPSCALE_STEP_QN 0x316f
#define HEVC_DBLK_DBLK0 0x3523
#define HEVC_DBLK_DBLK1 0x3524
#define HEVC_DBLK_DBLK2 0x3525
#define HW_MASK_FRONT 0x1
#define HW_MASK_BACK 0x2
#define AV1D_MPP_REFINFO_TBL_ACCCONFIG 0x3442
#define AV1D_MPP_REFINFO_DATA 0x3443
#define AV1D_MPP_REF_SCALE_ENBL 0x3441
#define HEVC_MPRED_CTRL4 0x324c
#define HEVC_CM_HEADER_START_ADDR 0x3628
#define HEVC_DBLK_CFGB 0x350b
#define HEVCD_MPP_ANC2AXI_TBL_DATA 0x3464
#define HEVC_SAO_MMU_VH1_ADDR 0x363b
#define HEVC_SAO_MMU_VH0_ADDR 0x363a
#define HEVC_MV_INFO 0x310d
#define HEVC_QP_INFO 0x3137
#define HEVC_SKIP_INFO 0x3136
#define HEVC_CM_BODY_LENGTH2 0x3663
#define HEVC_CM_HEADER_OFFSET2 0x3664
#define HEVC_CM_HEADER_LENGTH2 0x3665
#define HEVC_CM_HEADER_START_ADDR2 0x364a
#define HEVC_SAO_MMU_DMA_CTRL2 0x364c
#define HEVC_SAO_MMU_VH0_ADDR2 0x364d
#define HEVC_SAO_MMU_VH1_ADDR2 0x364e
#define HEVC_SAO_MMU_STATUS2 0x3650
#define HEVC_DW_VH0_ADDDR 0x365e
#define HEVC_DW_VH1_ADDDR 0x365f
#ifdef BUFMGR_ONLY_OLD_CHIP
#undef AV1_SKIP_MODE_INFO
#define AV1_SKIP_MODE_INFO HEVC_ASSIST_SCRATCH_B
#endif
#define AOM_AV1_DEC_IDLE 0
#define AOM_AV1_DEC_FRAME_HEADER 1
#define AOM_AV1_DEC_TILE_END 2
#define AOM_AV1_DEC_TG_END 3
#define AOM_AV1_DEC_LCU_END 4
#define AOM_AV1_DECODE_SLICE 5
#define AOM_AV1_SEARCH_HEAD 6
#define AOM_AV1_DUMP_LMEM 7
#define AOM_AV1_FGS_PARAM_CONT 8
#define AOM_AV1_DISCARD_NAL 0x10
/*status*/
#define AOM_AV1_DEC_PIC_END 0xe0
/*AOM_AV1_FGS_PARA:
Bit[11] - 0 Read, 1 - Write
Bit[10:8] - film_grain_params_ref_idx, For Write request
*/
#define AOM_AV1_FGS_PARAM 0xe1
#define AOM_AV1_DEC_PIC_END_PRE 0xe2
#define AOM_AV1_HEAD_PARSER_DONE 0xf0
#define AOM_AV1_HEAD_SEARCH_DONE 0xf1
#define AOM_AV1_SEQ_HEAD_PARSER_DONE 0xf2
#define AOM_AV1_FRAME_HEAD_PARSER_DONE 0xf3
#define AOM_AV1_FRAME_PARSER_DONE 0xf4
#define AOM_AV1_REDUNDANT_FRAME_HEAD_PARSER_DONE 0xf5
#define HEVC_ACTION_DONE 0xff
#define AOM_DECODE_BUFEMPTY 0x20
#define AOM_DECODE_TIMEOUT 0x21
#define AOM_SEARCH_BUFEMPTY 0x22
#define AOM_DECODE_OVER_SIZE 0x23
#define AOM_EOS 0x24
#define AOM_NAL_DECODE_DONE 0x25
#define VF_POOL_SIZE 32
#undef pr_info
#define pr_info printk
#define DECODE_MODE_SINGLE ((0x80 << 24) | 0)
#define DECODE_MODE_MULTI_STREAMBASE ((0x80 << 24) | 1)
#define DECODE_MODE_MULTI_FRAMEBASE ((0x80 << 24) | 2)
#define DECODE_MODE_SINGLE_LOW_LATENCY ((0x80 << 24) | 3)
#define DECODE_MODE_MULTI_FRAMEBASE_NOHEAD ((0x80 << 24) | 4)
#define AV1_TRIGGER_FRAME_DONE 0x100
#define AV1_TRIGGER_FRAME_ENABLE 0x200
#define MV_MEM_UNIT 0x240
/*---------------------------------------------------
* Include "parser_cmd.h"
*---------------------------------------------------
*/
#define PARSER_CMD_SKIP_CFG_0 0x0000090b
#define PARSER_CMD_SKIP_CFG_1 0x1b14140f
#define PARSER_CMD_SKIP_CFG_2 0x001b1910
#define PARSER_CMD_NUMBER 37
/*#define HEVC_PIC_STRUCT_SUPPORT*/
/* to remove, fix build error */
/*#define CODEC_MM_FLAGS_FOR_VDECODER 0*/
#define MULTI_INSTANCE_SUPPORT
#define SUPPORT_10BIT
/* #define ERROR_HANDLE_DEBUG */
#ifndef STAT_KTHREAD
#define STAT_KTHREAD 0x40
#endif
#ifdef MULTI_INSTANCE_SUPPORT
#define MAX_DECODE_INSTANCE_NUM 9
#ifdef DEBUG_USE_VP9_DEVICE_NAME
#define MULTI_DRIVER_NAME "ammvdec_vp9"
#else
#define MULTI_DRIVER_NAME "ammvdec_av1"
#endif
#define AUX_BUF_ALIGN(adr) ((adr + 0xf) & (~0xf))
#ifdef DEBUG_UCODE_LOG
static u32 prefix_aux_buf_size;
static u32 suffix_aux_buf_size;
#else
static u32 prefix_aux_buf_size = (16 * 1024);
static u32 suffix_aux_buf_size;
#endif
#if (defined DEBUG_UCODE_LOG) || (defined DEBUG_CMD)
//#define UCODE_LOG_BUF_SIZE (16 * 1024)
#define UCODE_LOG_BUF_SIZE (1024 * 1024)
#endif
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 AOM_AV1_MMU_DW
static unsigned int dw_mmu_enable[MAX_DECODE_INSTANCE_NUM];
#endif
/* disable timeout for av1 mosaic JIRA SWPL-23326 */
static u32 decode_timeout_val = 0;
static int start_decode_buf_level = 0x8000;
//static u32 work_buf_size;
static u32 force_pts_unstable;
static u32 mv_buf_margin = REF_FRAMES;
static u32 mv_buf_dynamic_alloc;
static u32 force_max_one_mv_buffer_size;
/* 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
* 0x20, mmu double write
* 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;
#ifdef DEBUG_USE_VP9_DEVICE_NAME
#define DRIVER_NAME "amvdec_vp9"
#define DRIVER_HEADER_NAME "amvdec_vp9_header"
#else
#define DRIVER_NAME "amvdec_av1"
#define DRIVER_HEADER_NAME "amvdec_av1_header"
#endif
#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 PTS2DUR(x) ((x)*96/90)
struct AV1HW_s;
static int vav1_vf_states(struct vframe_states *states, void *);
static struct vframe_s *vav1_vf_peek(void *);
static struct vframe_s *vav1_vf_get(void *);
static void vav1_vf_put(struct vframe_s *, void *);
static int vav1_event_cb(int type, void *data, void *private_data);
static int vav1_stop(struct AV1HW_s *hw);
#ifdef MULTI_INSTANCE_SUPPORT
static s32 vav1_init(struct vdec_s *vdec);
#else
static s32 vav1_init(struct AV1HW_s *hw);
#endif
static void vav1_prot_init(struct AV1HW_s *hw, u32 mask);
static int vav1_local_init(struct AV1HW_s *hw);
static void vav1_put_timer_func(unsigned long arg);
static void dump_data(struct AV1HW_s *hw, int size);
static unsigned int get_data_check_sum
(struct AV1HW_s *hw, int size);
static void dump_pic_list(struct AV1HW_s *hw);
static int vav1_mmu_map_alloc(struct AV1HW_s *hw);
static void vav1_mmu_map_free(struct AV1HW_s *hw);
static int av1_alloc_mmu(
struct AV1HW_s *hw,
int cur_buf_idx,
int pic_width,
int pic_height,
unsigned short bit_depth,
unsigned int *mmu_index_adr);
#ifdef DEBUG_USE_VP9_DEVICE_NAME
static const char vav1_dec_id[] = "vvp9-dev";
#define PROVIDER_NAME "decoder.vp9"
#define MULTI_INSTANCE_PROVIDER_NAME "vdec.vp9"
#else
static const char vav1_dec_id[] = "vav1-dev";
#define PROVIDER_NAME "decoder.av1"
#define MULTI_INSTANCE_PROVIDER_NAME "vdec.av1"
#endif
#define DV_PROVIDER_NAME "dvbldec"
static const struct vframe_operations_s vav1_vf_provider = {
.peek = vav1_vf_peek,
.get = vav1_vf_get,
.put = vav1_vf_put,
.event_cb = vav1_event_cb,
.vf_states = vav1_vf_states,
};
static struct vframe_provider_s vav1_vf_prov;
static u32 bit_depth_luma;
static u32 bit_depth_chroma;
static u32 frame_width;
static u32 frame_height;
static u32 video_signal_type;
static u32 on_no_keyframe_skiped;
static u32 without_display_mode;
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
static u32 force_dv_enable;
#endif
#define PROB_SIZE (496 * 2 * 4)
#define PROB_BUF_SIZE (0x5000)
#define COUNT_BUF_SIZE (0x300 * 4 * 4)
/*compute_losless_comp_body_size(4096, 2304, 1) = 18874368(0x1200000)*/
#define MAX_FRAME_4K_NUM 0x1200
#define MAX_FRAME_8K_NUM 0x4800
#define HEVC_ASSIST_MMU_MAP_ADDR 0x3009
/*USE_BUF_BLOCK*/
struct BUF_s {
int index;
unsigned int alloc_flag;
/*buffer */
unsigned int cma_page_count;
unsigned long alloc_addr;
unsigned long start_adr;
unsigned int size;
unsigned int free_start_adr;
ulong v4l_ref_buf_addr;
ulong header_addr;
u32 header_size;
u32 luma_size;
ulong chroma_addr;
u32 chroma_size;
} /*BUF_t */;
struct MVBUF_s {
unsigned long start_adr;
unsigned int size;
int used_flag;
} /*MVBUF_t */;
/*#define TEST_WR_PTR_INC*/
/*#define WR_PTR_INC_NUM 128*/
#define WR_PTR_INC_NUM 1
//#define SIMULATION
#define DOS_PROJECT
#undef MEMORY_MAP_IN_REAL_CHIP
/*#undef DOS_PROJECT*/
/*#define MEMORY_MAP_IN_REAL_CHIP*/
/*#define CONFIG_HEVC_CLK_FORCED_ON*/
/*#define ENABLE_SWAP_TEST*/
#ifndef BUFMGR_ONLY_OLD_CHIP
#define MCRCC_ENABLE
#endif
#ifdef AV1_10B_NV21
#else
#define LOSLESS_COMPRESS_MODE
#endif
typedef unsigned int u32;
typedef unsigned short u16;
static u32 get_picture_qos;
static u32 debug;
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;
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
static u32 dv_toggle_prov_name;
#endif
static u32 run_ready_min_buf_num = 2;
#ifdef DEBUG_CRC_ERROR
/*
bit[4] fill zero in header before starting
bit[5] dump mmu header always
bit[6] dump mv buffer always
bit[8] delay after decoding
bit[31~16] delayed mseconds
*/
static u32 crc_debug_flag;
#endif
#ifdef DEBUG_CMD
static u32 header_dump_size = 0x10000;
static u32 debug_cmd_wait_count;
static u32 debug_cmd_wait_type;
#endif
#
#define DEBUG_REG
#ifdef DEBUG_REG
void AV1_WRITE_VREG_DBG2(unsigned int adr, unsigned int val, int line)
{
if (debug & AV1_DEBUG_REG)
pr_info("%d:%s(%x, %x)\n", line, __func__, adr, val);
if (adr != 0)
WRITE_VREG(adr, val);
}
#undef WRITE_VREG
#define WRITE_VREG(a,v) AV1_WRITE_VREG_DBG2(a,v,__LINE__)
#endif
#define FRAME_CNT_WINDOW_SIZE 59
#define RATE_CORRECTION_THRESHOLD 5
/**************************************************
AV1 buffer management start
***************************************************/
#define MMU_COMPRESS_HEADER_SIZE_1080P 0x10000
#define MMU_COMPRESS_HEADER_SIZE_4K 0x48000
#define MMU_COMPRESS_HEADER_SIZE_8K 0x120000
//#define MMU_COMPRESS_HEADER_SIZE 0x48000
//#define MAX_ONE_MV_BUFFER_SIZE 0x260000
//#define MAX_ONE_MV_BUFFER_SIZE 0x130000
#define MAX_ONE_MV_BUFFER_SIZE_1080P 0x20400
#define MAX_ONE_MV_BUFFER_SIZE_4K 0x91400
#define MAX_ONE_MV_BUFFER_SIZE_8K 0x244800
/*to support tm2revb and sc2*/
#define MAX_ONE_MV_BUFFER_SIZE_1080P_TM2REVB 0x26400
#define MAX_ONE_MV_BUFFER_SIZE_4K_TM2REVB 0xac400
#define MAX_ONE_MV_BUFFER_SIZE_8K_TM2REVB 0x2b0800
static int vav1_mmu_compress_header_size(struct AV1HW_s *hw);
//#define MMU_COMPRESS_HEADER_SIZE 0x48000
//#define MMU_COMPRESS_HEADER_SIZE_DW MMU_COMPRESS_HEADER_SIZE
//#define MMU_COMPRESS_8K_HEADER_SIZE (0x48000*4)
#define MAX_SIZE_8K (8192 * 4608)
#define MAX_SIZE_4K (4096 * 2304)
#define IS_8K_SIZE(w, h) (((w) * (h)) > MAX_SIZE_4K)
#define IS_4K_SIZE(w, h) (((w) * (h)) > (1920*1088))
#define INVALID_IDX -1 /* Invalid buffer index.*/
/*4 scratch frames for the new frames to support a maximum of 4 cores decoding
*in parallel, 3 for scaled references on the encoder.
*TODO(hkuang): Add ondemand frame buffers instead of hardcoding the number
* // of framebuffers.
*TODO(jkoleszar): These 3 extra references could probably come from the
*normal reference pool.
*/
//#define FRAME_BUFFERS (REF_FRAMES + 16)
//#define REF_FRAMES_4K (6)
#define REF_FRAMES_4K REF_FRAMES
#ifdef USE_SPEC_BUF_FOR_MMU_HEAD
#define HEADER_FRAME_BUFFERS (0)
#elif (defined AOM_AV1_MMU_DW)
#define HEADER_FRAME_BUFFERS (2 * FRAME_BUFFERS)
#else
#define HEADER_FRAME_BUFFERS (FRAME_BUFFERS)
#endif
#define MAX_BUF_NUM (FRAME_BUFFERS)
#define MV_BUFFER_NUM FRAME_BUFFERS
//#define FRAME_CONTEXTS_LOG2 2
//#define FRAME_CONTEXTS (1 << FRAME_CONTEXTS_LOG2)
/*buffer + header buffer + workspace*/
#ifdef MV_USE_FIXED_BUF
#define MAX_BMMU_BUFFER_NUM (FRAME_BUFFERS + HEADER_FRAME_BUFFERS + 1)
#define VF_BUFFER_IDX(n) (n)
#define HEADER_BUFFER_IDX(n) (FRAME_BUFFERS + n)
#define WORK_SPACE_BUF_ID (FRAME_BUFFERS + HEADER_FRAME_BUFFERS)
#else
#define MAX_BMMU_BUFFER_NUM \
(FRAME_BUFFERS + HEADER_FRAME_BUFFERS + MV_BUFFER_NUM + 1)
#define VF_BUFFER_IDX(n) (n)
#define HEADER_BUFFER_IDX(n) (FRAME_BUFFERS + n)
#define MV_BUFFER_IDX(n) (FRAME_BUFFERS + HEADER_FRAME_BUFFERS + n)
#define WORK_SPACE_BUF_ID \
(FRAME_BUFFERS + HEADER_FRAME_BUFFERS + MV_BUFFER_NUM)
#endif
#ifdef AOM_AV1_MMU_DW
#define DW_HEADER_BUFFER_IDX(n) (HEADER_BUFFER_IDX(HEADER_FRAME_BUFFERS/2) + n)
#endif
static void set_canvas(struct AV1HW_s *hw,
struct PIC_BUFFER_CONFIG_s *pic_config);
static void fill_frame_info(struct AV1HW_s *hw,
struct PIC_BUFFER_CONFIG_s *frame,
unsigned int framesize,
unsigned int pts);
static int compute_losless_comp_body_size(int width, int height,
uint8_t is_bit_depth_10);
#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_S1_RESULT_NONE 0
#define DEC_S1_RESULT_DONE 1
#define DEC_S1_RESULT_FORCE_EXIT 2
#define DEC_S1_RESULT_TEST_TRIGGER_DONE 0xf0
#ifdef FB_DECODING_TEST_SCHEDULE
#define TEST_SET_NONE 0
#define TEST_SET_PIC_DONE 1
#define TEST_SET_S2_DONE 2
#endif
static void av1_work(struct work_struct *work);
#endif
#ifdef DUMP_FILMGRAIN
u32 fg_dump_index = 0xff;
#endif
#ifdef AOM_AV1_DBLK_INIT
struct loop_filter_info_n_s;
struct loopfilter;
struct segmentation_lf;
#endif
struct AV1HW_s {
AV1Decoder *pbi;
union param_u aom_param;
unsigned char frame_decoded;
unsigned char one_compressed_data_done;
unsigned char new_compressed_data;
#if 1
/*def CHECK_OBU_REDUNDANT_FRAME_HEADER*/
int obu_frame_frame_head_come_after_tile;
#endif
unsigned char index;
struct device *cma_dev;
struct platform_device *platform_dev;
void (*vdec_cb)(struct vdec_s *, void *);
void *vdec_cb_arg;
struct vframe_chunk_s *chunk;
int dec_result;
struct work_struct work;
struct work_struct set_clk_work;
u32 start_shift_bytes;
u32 data_size;
struct BuffInfo_s work_space_buf_store;
unsigned long buf_start;
u32 buf_size;
u32 cma_alloc_count;
unsigned long cma_alloc_addr;
uint8_t eos;
unsigned long int start_process_time;
unsigned last_lcu_idx;
int decode_timeout_count;
unsigned timeout_num;
int save_buffer_mode;
int double_write_mode;
long used_4k_num;
unsigned char m_ins_flag;
char *provider_name;
union param_u param;
int frame_count;
int pic_count;
u32 stat;
struct timer_list timer;
u32 frame_dur;
u32 frame_ar;
int fatal_error;
uint8_t init_flag;
uint8_t config_next_ref_info_flag;
uint8_t first_sc_checked;
uint8_t process_busy;
#define PROC_STATE_INIT 0
#define PROC_STATE_DECODESLICE 1
#define PROC_STATE_SENDAGAIN 2
uint8_t process_state;
u32 ucode_pause_pos;
int show_frame_num;
struct buff_s mc_buf_spec;
struct dec_sysinfo vav1_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;
#ifdef DUMP_FILMGRAIN
dma_addr_t fg_phy_addr;
unsigned char *fg_ptr;
void *fg_addr;
#endif
u32 fgs_valid;
u8 aux_data_dirty;
u32 prefix_aux_size;
u32 suffix_aux_size;
void *aux_addr;
dma_addr_t aux_phy_addr;
char *dv_data_buf;
int dv_data_size;
#if (defined DEBUG_UCODE_LOG) || (defined DEBUG_CMD)
void *ucode_log_addr;
dma_addr_t ucode_log_phy_addr;
#endif
void *prob_buffer_addr;
void *count_buffer_addr;
dma_addr_t prob_buffer_phy_addr;
dma_addr_t count_buffer_phy_addr;
void *frame_mmu_map_addr;
dma_addr_t frame_mmu_map_phy_addr;
#ifdef AOM_AV1_MMU_DW
void *dw_frame_mmu_map_addr;
dma_addr_t dw_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[MV_BUFFER_NUM];
u32 used_buf_num;
u32 mv_buf_margin;
DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE);
DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE);
DECLARE_KFIFO(pending_q, struct vframe_s *, VF_POOL_SIZE);
struct vframe_s vfpool[VF_POOL_SIZE];
u32 vf_pre_count;
u32 vf_get_count;
u32 vf_put_count;
int buf_num;
int pic_num;
int lcu_size_log2;
unsigned int losless_comp_body_size;
u32 video_signal_type;
u32 pts_unstable;
bool av1_first_pts_ready;
bool dur_recalc_flag;
u8 first_pts_index;
u32 frame_mode_pts_save[FRAME_BUFFERS];
u64 frame_mode_pts64_save[FRAME_BUFFERS];
u64 frame_mode_timestamp_save[FRAME_BUFFERS];
u64 timestamp_duration;
int last_pts;
u64 last_pts_us64;
u64 last_timestamp;
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;
/**/
struct AV1_Common_s common;
struct RefCntBuffer_s *cur_buf;
int refresh_frame_flags;
uint8_t need_resync;
uint8_t hold_ref_buf;
uint8_t ready_for_new_data;
struct BufferPool_s av1_buffer_pool;
struct BuffInfo_s *work_space_buf;
struct buff_s *mc_buf;
unsigned int frame_width;
unsigned int frame_height;
unsigned short *rpm_ptr;
int init_pic_w;
int init_pic_h;
int lcu_total;
int current_lcu_size;
int slice_type;
int skip_flag;
int decode_idx;
int result_done_count;
uint8_t has_keyframe;
uint8_t has_sequence;
uint8_t wait_buf;
uint8_t error_flag;
/* bit 0, for decoding; bit 1, for displaying */
uint8_t ignore_bufmgr_error;
int PB_skip_mode;
int PB_skip_count_after_decoding;
/*hw*/
/**/
struct vdec_info *gvs;
u32 pre_stream_offset;
unsigned int dec_status;
u32 last_put_idx;
int new_frame_displayed;
void *mmu_box;
void *bmmu_box;
int mmu_enable;
#ifdef AOM_AV1_MMU_DW
void *mmu_box_dw;
int dw_mmu_enable;
#endif
struct vframe_master_display_colour_s vf_dp;
struct firmware_s *fw;
int max_pic_w;
int max_pic_h;
int buffer_spec_index;
int32_t max_one_mv_buffer_size;
int need_cache_size;
u64 sc_start_time;
bool postproc_done;
int low_latency_flag;
bool no_head;
bool pic_list_init_done;
bool pic_list_init_done2;
bool is_used_v4l;
void *v4l2_ctx;
bool v4l_params_parsed;
int frameinfo_enable;
struct vframe_qos_s vframe_qos;
#ifdef AOM_AV1_DBLK_INIT
/*
* malloc may not work in real chip, please allocate memory for the following structures
*/
struct loop_filter_info_n_s *lfi;
struct loopfilter *lf;
struct segmentation_lf *seg_4lf;
#endif
u32 mem_map_mode;
u32 dynamic_buf_num_margin;
struct vframe_s vframe_dummy;
u32 res_ch_flag;
int buffer_wrap[FRAME_BUFFERS];
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 void av1_dump_state(struct vdec_s *vdec);
int av1_print(struct AV1HW_s *hw,
int flag, const char *fmt, ...)
{
#define HEVC_PRINT_BUF 256
unsigned char buf[HEVC_PRINT_BUF];
int len = 0;
if (hw == NULL ||
(flag == 0) ||
(debug & flag)) {
va_list args;
va_start(args, fmt);
if (hw)
len = sprintf(buf, "[%d]", hw->index);
vsnprintf(buf + len, HEVC_PRINT_BUF - len, fmt, args);
pr_info("%s", buf);
va_end(args);
}
return 0;
}
unsigned char av1_is_debug(int flag)
{
if ((flag == 0) || (debug & flag))
return 1;
return 0;
}
int av1_print2(int flag, const char *fmt, ...)
{
unsigned char buf[HEVC_PRINT_BUF];
int len = 0;
if ((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;
}
static int is_oversize(int w, int h)
{
int max = (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1)?
MAX_SIZE_8K : MAX_SIZE_4K;
if (w <= 0 || h <= 0)
return true;
if (h != 0 && (w > max / h))
return true;
return false;
}
static int v4l_alloc_and_config_pic(struct AV1HW_s *hw,
struct PIC_BUFFER_CONFIG_s *pic);
static inline bool close_to(int a, int b, int m)
{
return (abs(a - b) < m) ? true : false;
}
#ifdef MULTI_INSTANCE_SUPPORT
static int av1_print_cont(struct AV1HW_s *hw,
int flag, const char *fmt, ...)
{
unsigned char buf[HEVC_PRINT_BUF];
int len = 0;
if (hw == 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;
}
static void trigger_schedule(struct AV1HW_s *hw)
{
if (hw->is_used_v4l) {
struct aml_vcodec_ctx *ctx =
(struct aml_vcodec_ctx *)(hw->v4l2_ctx);
if (ctx->param_sets_from_ucode &&
!hw->v4l_params_parsed)
vdec_v4l_write_frame_sync(ctx);
}
if (hw->vdec_cb)
hw->vdec_cb(hw_to_vdec(hw), hw->vdec_cb_arg);
}
static void reset_process_time(struct AV1HW_s *hw)
{
if (hw->start_process_time) {
unsigned process_time =
1000 * (jiffies - hw->start_process_time) / HZ;
hw->start_process_time = 0;
if (process_time > max_process_time[hw->index])
max_process_time[hw->index] = process_time;
}
}
static void start_process_time(struct AV1HW_s *hw)
{
hw->start_process_time = jiffies;
hw->decode_timeout_count = 0;
hw->last_lcu_idx = 0;
}
static void timeout_process(struct AV1HW_s *hw)
{
reset_process_time(hw);
if (hw->process_busy) {
av1_print(hw,
0, "%s decoder timeout but process_busy\n", __func__);
if (debug)
av1_print(hw, 0, "debug disable timeout notify\n");
return;
}
hw->timeout_num++;
amhevc_stop();
av1_print(hw,
0, "%s decoder timeout\n", __func__);
hw->dec_result = DEC_RESULT_DONE;
vdec_schedule_work(&hw->work);
}
static u32 get_valid_double_write_mode(struct AV1HW_s *hw)
{
u32 dw = ((double_write_mode & 0x80000000) == 0) ?
hw->double_write_mode :
(double_write_mode & 0x7fffffff);
if ((dw & 0x20) &&
((dw & 0xf) == 2 || (dw & 0xf) == 3)) {
pr_info("MMU doueble write 1:4 not supported !!!\n");
dw = 0;
}
return dw;
}
static int v4l_parser_get_double_write_mode(struct AV1HW_s *hw)
{
u32 valid_dw_mode = get_valid_double_write_mode(hw);
u32 dw;
int w, h;
/* mask for supporting double write value bigger than 0x100 */
if (valid_dw_mode & 0xffffff00) {
w = hw->frame_width;
h = hw->frame_height;
dw = 0x1; /*1:1*/
switch (valid_dw_mode) {
case 0x100:
if (w > 1920 && h > 1088)
dw = 0x4; /*1:2*/
break;
case 0x200:
if (w > 1920 && h > 1088)
dw = 0x2; /*1:4*/
break;
case 0x300:
if (w > 1280 && h > 720)
dw = 0x4; /*1:2*/
break;
default:
break;
}
return dw;
}
return valid_dw_mode;
}
static int get_double_write_mode(struct AV1HW_s *hw)
{
u32 valid_dw_mode = get_valid_double_write_mode(hw);
u32 dw;
int w, h;
struct AV1_Common_s *cm = &hw->common;
struct PIC_BUFFER_CONFIG_s *cur_pic_config;
if (!cm->cur_frame)
return 1;/*no valid frame,*/
cur_pic_config = &cm->cur_frame->buf;
w = cur_pic_config->y_crop_width;
h = cur_pic_config->y_crop_height;
dw = 0x1; /*1:1*/
switch (valid_dw_mode) {
case 0x100:
if (w > 1920 && h > 1088)
dw = 0x4; /*1:2*/
break;
case 0x200:
if (w > 1920 && h > 1088)
dw = 0x2; /*1:4*/
break;
case 0x300:
if (w > 1280 && h > 720)
dw = 0x4; /*1:2*/
break;
default:
dw = valid_dw_mode;
break;
}
return dw;
}
/* for double write buf alloc */
static int get_double_write_mode_init(struct AV1HW_s *hw)
{
u32 valid_dw_mode = get_valid_double_write_mode(hw);
u32 dw;
int w = hw->init_pic_w;
int h = hw->init_pic_h;
dw = 0x1; /*1:1*/
switch (valid_dw_mode) {
case 0x100:
if (w > 1920 && h > 1088)
dw = 0x4; /*1:2*/
break;
case 0x200:
if (w > 1920 && h > 1088)
dw = 0x2; /*1:4*/
break;
case 0x300:
if (w > 1280 && h > 720)
dw = 0x4; /*1:2*/
break;
default:
dw = valid_dw_mode;
break;
}
return dw;
}
#endif
static int get_double_write_ratio(struct AV1HW_s *hw,
int dw_mode)
{
int ratio = 1;
int dw_mode_ratio = dw_mode & 0xf;
if ((dw_mode_ratio == 2) ||
(dw_mode_ratio == 3))
ratio = 4;
else if (dw_mode_ratio == 4)
ratio = 2;
return ratio;
}
/* return page number */
static int av1_mmu_page_num(struct AV1HW_s *hw,
int w, int h, int save_mode)
{
int picture_size;
int cur_mmu_4k_number, max_frame_num;
picture_size = compute_losless_comp_body_size(w, h, save_mode);
cur_mmu_4k_number = ((picture_size + (PAGE_SIZE - 1)) >> PAGE_SHIFT);
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, w, h);
return -1;
}
return cur_mmu_4k_number;
}
//#define MAX_4K_NUM 0x1200
int av1_alloc_mmu(
struct AV1HW_s *hw,
int cur_buf_idx,
int pic_width,
int pic_height,
unsigned short bit_depth,
unsigned int *mmu_index_adr)
{
int ret = 0;
int bit_depth_10 = (bit_depth == AOM_BITS_10);
int cur_mmu_4k_number;
if (!hw->mmu_box) {
pr_err("error no mmu box!\n");
return -1;
}
if (hw->double_write_mode & 0x10)
return 0;
if (bit_depth >= AOM_BITS_12) {
hw->fatal_error = DECODER_FATAL_ERROR_SIZE_OVERFLOW;
pr_err("fatal_error, un support bit depth 12!\n\n");
return -1;
}
cur_mmu_4k_number = av1_mmu_page_num(hw,
pic_width,
pic_height,
bit_depth_10);
if (cur_mmu_4k_number < 0)
return -1;
ret = decoder_mmu_box_alloc_idx(
hw->mmu_box,
hw->buffer_wrap[cur_buf_idx],
cur_mmu_4k_number,
mmu_index_adr);
return ret;
}
#ifdef AOM_AV1_MMU_DW
static int compute_losless_comp_body_size_dw(int width, int height,
uint8_t is_bit_depth_10);
int av1_alloc_mmu_dw(
struct AV1HW_s *hw,
int cur_buf_idx,
int pic_width,
int pic_height,
unsigned short bit_depth,
unsigned int *mmu_index_adr)
{
int ret = 0;
int bit_depth_10 = (bit_depth == AOM_BITS_10);
int picture_size;
int cur_mmu_4k_number, max_frame_num;
if (!hw->mmu_box_dw) {
pr_err("error no mmu box!\n");
return -1;
}
if (hw->double_write_mode & 0x10)
return 0;
if (bit_depth >= AOM_BITS_12) {
hw->fatal_error = DECODER_FATAL_ERROR_SIZE_OVERFLOW;
pr_err("fatal_error, un support bit depth 12!\n\n");
return -1;
}
picture_size = compute_losless_comp_body_size_dw(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;
}
ret = decoder_mmu_box_alloc_idx(
hw->mmu_box_dw,
hw->buffer_wrap[cur_buf_idx],
cur_mmu_4k_number,
mmu_index_adr);
return ret;
}
#endif
#ifndef MV_USE_FIXED_BUF
static void dealloc_mv_bufs(struct AV1HW_s *hw)
{
int i;
for (i = 0; i < MV_BUFFER_NUM; i++) {
if (hw->m_mv_BUF[i].start_adr) {
if (debug)
pr_info(
"dealloc mv buf(%d) adr %ld size 0x%x used_flag %d\n",
i, hw->m_mv_BUF[i].start_adr,
hw->m_mv_BUF[i].size,
hw->m_mv_BUF[i].used_flag);
decoder_bmmu_box_free_idx(
hw->bmmu_box,
MV_BUFFER_IDX(i));
hw->m_mv_BUF[i].start_adr = 0;
hw->m_mv_BUF[i].size = 0;
hw->m_mv_BUF[i].used_flag = 0;
}
}
}
static int alloc_mv_buf(struct AV1HW_s *hw,
int i, int size)
{
int ret = 0;
if (decoder_bmmu_box_alloc_buf_phy
(hw->bmmu_box,
MV_BUFFER_IDX(i), size,
DRIVER_NAME,
&hw->m_mv_BUF[i].start_adr) < 0) {
hw->m_mv_BUF[i].start_adr = 0;
ret = -1;
} else {
hw->m_mv_BUF[i].size = size;
hw->m_mv_BUF[i].used_flag = 0;
ret = 0;
if (debug) {
pr_info(
"MV Buffer %d: start_adr %p size %x\n",
i,
(void *)hw->m_mv_BUF[i].start_adr,
hw->m_mv_BUF[i].size);
}
}
return ret;
}
static int cal_mv_buf_size(struct AV1HW_s *hw, int pic_width, int pic_height)
{
unsigned lcu_size = hw->current_lcu_size;
int extended_pic_width = (pic_width + lcu_size -1)
& (~(lcu_size - 1));
int extended_pic_height = (pic_height + lcu_size -1)
& (~(lcu_size - 1));
int lcu_x_num = extended_pic_width / lcu_size;
int lcu_y_num = extended_pic_height / lcu_size;
int size_a, size_b, size;
if (get_cpu_major_id() > AM_MESON_CPU_MAJOR_ID_SC2)
/*tm2revb and sc2*/
size_a = lcu_x_num * lcu_y_num * 16 *
((lcu_size == 64) ? 16 : 64);
else
size_a = lcu_x_num * lcu_y_num * 16 *
((lcu_size == 64) ? 19 : 76);
size_b = lcu_x_num * ((lcu_y_num >> 3) +
(lcu_y_num & 0x7)) * 16;
size = ((size_a + size_b) + 0xffff) & (~0xffff);
if (debug & AOM_DEBUG_USE_FIXED_MV_BUF_SIZE)
size = hw->max_one_mv_buffer_size;
if (force_max_one_mv_buffer_size)
size = force_max_one_mv_buffer_size;
return size;
}
static int init_mv_buf_list(struct AV1HW_s *hw)
{
int i;
int ret = 0;
int count = MV_BUFFER_NUM;
int pic_width = hw->init_pic_w;
int pic_height = hw->init_pic_h;
int size = cal_mv_buf_size(hw, pic_width, pic_height);
if (mv_buf_dynamic_alloc)
return 0;
#if 0
if (mv_buf_margin > 0)
count = REF_FRAMES + mv_buf_margin;
if (hw->init_pic_w > 2048 && hw->init_pic_h > 1088)
count = REF_FRAMES_4K + mv_buf_margin;
#else
if (debug)
pr_info("%s, calculated mv size 0x%x\n",
__func__, size);
if ((hw->is_used_v4l) && !IS_8K_SIZE(pic_width, pic_height)) {
if (vdec_is_support_4k())
size = 0xb0000;
else
size = 0x30000;
}
if (hw->init_pic_w > 4096 && hw->init_pic_h > 2048)
count = REF_FRAMES_4K + hw->mv_buf_margin;
else if (hw->init_pic_w > 2048 && hw->init_pic_h > 1088)
count = REF_FRAMES_4K + hw->mv_buf_margin;
else
count = REF_FRAMES + hw->mv_buf_margin;
#endif
if (debug) {
pr_info("%s w:%d, h:%d, count: %d, size 0x%x\n",
__func__, hw->init_pic_w, hw->init_pic_h,
count, size);
}
for (i = 0;
i < count && i < MV_BUFFER_NUM; i++) {
if (alloc_mv_buf(hw, i, size) < 0) {
ret = -1;
break;
}
}
return ret;
}
static int get_mv_buf(struct AV1HW_s *hw,
struct PIC_BUFFER_CONFIG_s *pic_config)
{
int i;
int ret = -1;
if (mv_buf_dynamic_alloc) {
int size = cal_mv_buf_size(hw,
pic_config->y_crop_width, pic_config->y_crop_height);
for (i = 0; i < MV_BUFFER_NUM; i++) {
if (hw->m_mv_BUF[i].start_adr == 0) {
ret = i;
break;
}
}
if (i == MV_BUFFER_NUM) {
pr_info(
"%s: Error, mv buf MV_BUFFER_NUM is not enough\n",
__func__);
return ret;
}
if (alloc_mv_buf(hw, ret, size) >= 0) {
pic_config->mv_buf_index = ret;
pic_config->mpred_mv_wr_start_addr =
(hw->m_mv_BUF[ret].start_adr + 0xffff) &
(~0xffff);
} else {
pr_info(
"%s: Error, mv buf alloc fail\n",
__func__);
}
return ret;
}
for (i = 0; i < MV_BUFFER_NUM; i++) {
if (hw->m_mv_BUF[i].start_adr &&
hw->m_mv_BUF[i].used_flag == 0) {
hw->m_mv_BUF[i].used_flag = 1;
ret = i;
break;
}
}
if (ret >= 0) {
pic_config->mv_buf_index = ret;
pic_config->mpred_mv_wr_start_addr =
(hw->m_mv_BUF[ret].start_adr + 0xffff) &
(~0xffff);
if (debug & AV1_DEBUG_BUFMGR_MORE)
pr_info(
"%s => %d (%d) size 0x%x\n",
__func__, ret,
pic_config->mpred_mv_wr_start_addr,
hw->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 AV1HW_s *hw,
int *mv_buf_index)
{
int i = *mv_buf_index;
if (i >= MV_BUFFER_NUM) {
if (debug & AV1_DEBUG_BUFMGR_MORE)
pr_info(
"%s: index %d beyond range\n",
__func__, i);
return;
}
if (mv_buf_dynamic_alloc) {
if (hw->m_mv_BUF[i].start_adr) {
if (debug)
pr_info(
"dealloc mv buf(%d) adr %ld size 0x%x used_flag %d\n",
i, hw->m_mv_BUF[i].start_adr,
hw->m_mv_BUF[i].size,
hw->m_mv_BUF[i].used_flag);
decoder_bmmu_box_free_idx(
hw->bmmu_box,
MV_BUFFER_IDX(i));
hw->m_mv_BUF[i].start_adr = 0;
hw->m_mv_BUF[i].size = 0;
hw->m_mv_BUF[i].used_flag = 0;
}
*mv_buf_index = -1;
return;
}
if (debug & AV1_DEBUG_BUFMGR_MORE)
pr_info(
"%s(%d): used_flag(%d)\n",
__func__, i,
hw->m_mv_BUF[i].used_flag);
*mv_buf_index = -1;
if (hw->m_mv_BUF[i].start_adr &&
hw->m_mv_BUF[i].used_flag)
hw->m_mv_BUF[i].used_flag = 0;
}
static void put_un_used_mv_bufs(struct AV1HW_s *hw)
{
struct AV1_Common_s *const cm = &hw->common;
struct RefCntBuffer_s *const frame_bufs = cm->buffer_pool->frame_bufs;
int i;
for (i = 0; i < hw->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(hw, &frame_bufs[i].buf.mv_buf_index);
}
}
#endif
static void init_pic_list_hw(struct AV1HW_s *pbi);
static int get_free_fb_idx(AV1_COMMON *cm)
{
int i;
RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs;
for (i = 0; i < FRAME_BUFFERS; ++i) {
if (frame_bufs[i].ref_count == 0
&& frame_bufs[i].buf.vf_ref == 0)
break;
}
return i;
}
static int v4l_get_free_fb(struct AV1HW_s *hw)
{
struct AV1_Common_s *const cm = &hw->common;
struct RefCntBuffer_s *const frame_bufs = cm->buffer_pool->frame_bufs;
struct aml_vcodec_ctx * v4l = hw->v4l2_ctx;
struct v4l_buff_pool *pool = &v4l->cap_pool;
struct PIC_BUFFER_CONFIG_s *pic = NULL;
struct PIC_BUFFER_CONFIG_s *free_pic = NULL;
ulong flags;
int idx, i;
lock_buffer_pool(cm->buffer_pool, flags);
for (i = 0; i < pool->in; ++i) {
u32 state = (pool->seq[i] >> 16);
u32 index = (pool->seq[i] & 0xffff);
switch (state) {
case V4L_CAP_BUFF_IN_DEC:
pic = &frame_bufs[i].buf;
if ((frame_bufs[i].ref_count == 0) &&
(pic->vf_ref == 0) &&
(pic->index != -1) &&
pic->cma_alloc_addr) {
free_pic = pic;
}
break;
case V4L_CAP_BUFF_IN_M2M:
idx = get_free_fb_idx(cm);
pic = &frame_bufs[idx].buf;
pic->y_crop_width = hw->frame_width;
pic->y_crop_height = hw->frame_height;
hw->buffer_wrap[idx] = index;
if (!v4l_alloc_and_config_pic(hw, pic)) {
set_canvas(hw, pic);
init_pic_list_hw(hw);
free_pic = pic;
}
break;
default:
pr_err("v4l buffer state err %d.\n", state);
break;
}
if (free_pic) {
if (frame_bufs[i].buf.use_external_reference_buffers) {
// If this frame buffer's y_buffer, u_buffer, and v_buffer point to the
// external reference buffers. Restore the buffer pointers to point to the
// internally allocated memory.
PIC_BUFFER_CONFIG *ybf = &frame_bufs[i].buf;
ybf->y_buffer = ybf->store_buf_adr[0];
ybf->u_buffer = ybf->store_buf_adr[1];
ybf->v_buffer = ybf->store_buf_adr[2];
ybf->use_external_reference_buffers = 0;
}
frame_bufs[i].ref_count = 1;
break;
}
}
unlock_buffer_pool(cm->buffer_pool, flags);
return free_pic ? free_pic->index : INVALID_IDX;
}
static int get_free_fb(AV1_COMMON *cm) {
RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs;
unsigned long flags;
int i;
lock_buffer_pool(cm->buffer_pool, flags);
for (i = 0; i < FRAME_BUFFERS; ++i) {
if (frame_bufs[i].ref_count == 0
#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
&& frame_bufs[i].buf.vf_ref == 0
#endif
)
break;
}
if (i != FRAME_BUFFERS) {
if (frame_bufs[i].buf.use_external_reference_buffers) {
// If this frame buffer's y_buffer, u_buffer, and v_buffer point to the
// external reference buffers. Restore the buffer pointers to point to the
// internally allocated memory.
PIC_BUFFER_CONFIG *ybf = &frame_bufs[i].buf;
ybf->y_buffer = ybf->store_buf_adr[0];
ybf->u_buffer = ybf->store_buf_adr[1];
ybf->v_buffer = ybf->store_buf_adr[2];
ybf->use_external_reference_buffers = 0;
}
frame_bufs[i].ref_count = 1;
} else {
// We should never run out of free buffers. If this assertion fails, there
// is a reference leak.
//assert(0 && "Ran out of free frame buffers. Likely a reference leak.");
// Reset i to be INVALID_IDX to indicate no free buffer found.
i = INVALID_IDX;
}
unlock_buffer_pool(cm->buffer_pool, flags);
return i;
}
int get_free_frame_buffer(struct AV1_Common_s *cm)
{
struct AV1HW_s *hw = container_of(cm, struct AV1HW_s, common);
return hw->is_used_v4l ? v4l_get_free_fb(hw) : get_free_fb(cm);
}
static int get_free_buf_count(struct AV1HW_s *hw)
{
struct AV1_Common_s *const cm = &hw->common;
struct RefCntBuffer_s *const frame_bufs = cm->buffer_pool->frame_bufs;
int i;
int free_buf_count = 0;
for (i = 0; i < hw->used_buf_num; ++i)
if ((frame_bufs[i].ref_count == 0) &&
(frame_bufs[i].buf.vf_ref == 0) &&
(frame_bufs[i].buf.index != -1)
)
free_buf_count++;
return free_buf_count;
}
int aom_bufmgr_init(struct AV1HW_s *hw, struct BuffInfo_s *buf_spec_i,
struct buff_s *mc_buf_i) {
struct AV1_Common_s *cm = &hw->common;
if (debug)
pr_info("%s %d %p\n", __func__, __LINE__, hw->pbi);
hw->frame_count = 0;
hw->pic_count = 0;
hw->pre_stream_offset = 0;
spin_lock_init(&cm->buffer_pool->lock);
cm->prev_fb_idx = INVALID_IDX;
cm->new_fb_idx = INVALID_IDX;
hw->used_4k_num = -1;
cm->cur_fb_idx_mmu = INVALID_IDX;
pr_debug
("After aom_bufmgr_init, prev_fb_idx : %d, new_fb_idx : %d\r\n",
cm->prev_fb_idx, cm->new_fb_idx);
hw->need_resync = 1;
cm->current_video_frame = 0;
hw->ready_for_new_data = 1;
/* private init */
hw->work_space_buf = buf_spec_i;
if (!hw->mmu_enable)
hw->mc_buf = mc_buf_i;
hw->rpm_addr = NULL;
hw->lmem_addr = NULL;
#ifdef DUMP_FILMGRAIN
hw->fg_addr = NULL;
#endif
hw->use_cma_flag = 0;
hw->decode_idx = 0;
hw->result_done_count = 0;
/*int m_uiMaxCUWidth = 1<<7;*/
/*int m_uiMaxCUHeight = 1<<7;*/
hw->has_keyframe = 0;
hw->has_sequence = 0;
hw->skip_flag = 0;
hw->wait_buf = 0;
hw->error_flag = 0;
hw->last_pts = 0;
hw->last_pts_us64 = 0;
hw->last_timestamp = 0;
hw->shift_byte_count = 0;
hw->shift_byte_count_lo = 0;
hw->shift_byte_count_hi = 0;
hw->pts_mode_switching_count = 0;
hw->pts_mode_recovery_count = 0;
hw->buf_num = 0;
hw->pic_num = 0;
return 0;
}
/*
struct AV1HW_s av1_decoder;
union param_u av1_param;
*/
/**************************************************
*
*AV1 buffer management end
*
***************************************************
*/
#define HEVC_CM_BODY_START_ADDR 0x3626
#define HEVC_CM_BODY_LENGTH 0x3627
#define HEVC_CM_HEADER_LENGTH 0x3629
#define HEVC_CM_HEADER_OFFSET 0x362b
#define LOSLESS_COMPRESS_MODE
/*#define DECOMP_HEADR_SURGENT*/
#ifdef AV1_10B_NV21
static u32 mem_map_mode = 2 /* 0:linear 1:32x32 2:64x32*/
#else
static u32 mem_map_mode; /* 0:linear 1:32x32 2:64x32 ; m8baby test1902 */
#endif
static u32 enable_mem_saving = 1;
static u32 force_w_h;
static u32 force_fps;
const u32 av1_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;
static u32 multi_frames_in_one_pack = 1;
#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 av1_max_pic_w = 4096;
static u32 av1_max_pic_h = 2304;
static u32 dynamic_buf_num_margin = 3;
#else
static u32 buf_alloc_width;
static u32 buf_alloc_height;
static u32 dynamic_buf_num_margin = 7;
#endif
static u32 buf_alloc_depth = 10;
static u32 buf_alloc_size;
/*
*bit[0]: 0,
* bit[1]: 0, always release cma buffer when stop
* bit[1]: 1, never release cma buffer when stop
*bit[0]: 1, when stop, release cma buffer if blackout is 1;
*do not release cma buffer is blackout is not 1
*
*bit[2]: 0, when start decoding, check current displayed buffer
* (only for buffer decoded by AV1) if blackout is 0
* 1, do not check current displayed buffer
*
*bit[3]: 1, if blackout is not 1, do not release current
* displayed cma buffer always.
*/
/* set to 1 for fast play;
* set to 8 for other case of "keep last frame"
*/
static u32 buffer_mode = 1;
/* buffer_mode_dbg: debug only*/
static u32 buffer_mode_dbg = 0xffff0000;
/**/
/*
*bit 0, 1: only display I picture;
*bit 1, 1: only decode I picture;
*/
static u32 i_only_flag;
static u32 low_latency_flag;
static u32 no_head;
static u32 max_decoding_time;
/*
*error handling
*/
/*error_handle_policy:
*bit 0: 0, auto skip error_skip_nal_count nals before error recovery;
*1, skip error_skip_nal_count nals before error recovery;
*bit 1 (valid only when bit0 == 1):
*1, wait vps/sps/pps after error recovery;
*bit 2 (valid only when bit0 == 0):
*0, auto search after error recovery (av1_recover() called);
*1, manual search after error recovery
*(change to auto search after get IDR: WRITE_VREG(NAL_SEARCH_CTL, 0x2))
*
*bit 4: 0, set error_mark after reset/recover
* 1, do not set error_mark after reset/recover
*bit 5: 0, check total lcu for every picture
* 1, do not check total lcu
*
*/
static u32 error_handle_policy;
/*static u32 parser_sei_enable = 1;*/
#define MAX_BUF_NUM_NORMAL 16
/*less bufs num 12 caused frame drop, nts failed*/
#define MAX_BUF_NUM_LESS 14
static u32 max_buf_num = MAX_BUF_NUM_NORMAL;
#define MAX_BUF_NUM_SAVE_BUF 8
static DEFINE_MUTEX(vav1_mutex);
#ifndef MULTI_INSTANCE_SUPPORT
static struct device *cma_dev;
#endif
#define HEVC_DEC_STATUS_REG HEVC_ASSIST_SCRATCH_0
#define HEVC_FG_STATUS HEVC_ASSIST_SCRATCH_B
#define HEVC_RPM_BUFFER HEVC_ASSIST_SCRATCH_1
#define AOM_AV1_ADAPT_PROB_REG HEVC_ASSIST_SCRATCH_3
#define AOM_AV1_MMU_MAP_BUFFER HEVC_ASSIST_SCRATCH_4 // changed to use HEVC_ASSIST_MMU_MAP_ADDR
#define AOM_AV1_DAALA_TOP_BUFFER HEVC_ASSIST_SCRATCH_5
//#define HEVC_SAO_UP HEVC_ASSIST_SCRATCH_6
//#define HEVC_STREAM_SWAP_BUFFER HEVC_ASSIST_SCRATCH_7
#define AOM_AV1_CDF_BUFFER_W HEVC_ASSIST_SCRATCH_8
#define AOM_AV1_CDF_BUFFER_R HEVC_ASSIST_SCRATCH_9
#define AOM_AV1_COUNT_SWAP_BUFFER HEVC_ASSIST_SCRATCH_A
#define AOM_AV1_SEG_MAP_BUFFER_W AV1_SEG_W_ADDR // HEVC_ASSIST_SCRATCH_B
#define AOM_AV1_SEG_MAP_BUFFER_R AV1_SEG_R_ADDR // HEVC_ASSIST_SCRATCH_C
//#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 HEVC_STREAM_SWAP_TEST HEVC_ASSIST_SCRATCH_L
#ifdef MULTI_INSTANCE_SUPPORT
#define HEVC_DECODE_COUNT HEVC_ASSIST_SCRATCH_M
#define HEVC_DECODE_SIZE HEVC_ASSIST_SCRATCH_N
#else
#define HEVC_DECODE_PIC_BEGIN_REG HEVC_ASSIST_SCRATCH_M
#define HEVC_DECODE_PIC_NUM_REG HEVC_ASSIST_SCRATCH_N
#endif
#define AOM_AV1_SEGMENT_FEATURE AV1_QUANT_WR
#define DEBUG_REG1 HEVC_ASSIST_SCRATCH_G
#define DEBUG_REG2 HEVC_ASSIST_SCRATCH_H
#define LMEM_DUMP_ADR HEVC_ASSIST_SCRATCH_I
#define CUR_NAL_UNIT_TYPE HEVC_ASSIST_SCRATCH_J
#define DECODE_STOP_POS HEVC_ASSIST_SCRATCH_K
#define PIC_END_LCU_COUNT HEVC_ASSIST_SCRATCH_2
#define HEVC_AUX_ADR HEVC_ASSIST_SCRATCH_L
#define HEVC_AUX_DATA_SIZE HEVC_ASSIST_SCRATCH_7
#if (defined DEBUG_UCODE_LOG) || (defined DEBUG_CMD)
#define HEVC_DBG_LOG_ADR HEVC_ASSIST_SCRATCH_C
#ifdef DEBUG_CMD
#define HEVC_D_ADR HEVC_ASSIST_SCRATCH_4
#endif
#endif
/*
*ucode parser/search control
*bit 0: 0, header auto parse; 1, header manual parse
*bit 1: 0, auto skip for noneseamless stream; 1, no skip
*bit [3:2]: valid when bit1==0;
*0, auto skip nal before first vps/sps/pps/idr;
*1, auto skip nal before first vps/sps/pps
*2, auto skip nal before first vps/sps/pps,
* and not decode until the first I slice (with slice address of 0)
*
*3, auto skip before first I slice (nal_type >=16 && nal_type<=21)
*bit [15:4] nal skip count (valid when bit0 == 1 (manual mode) )
*bit [16]: for NAL_UNIT_EOS when bit0 is 0:
* 0, send SEARCH_DONE to arm ; 1, do not send SEARCH_DONE to arm
*bit [17]: for NAL_SEI when bit0 is 0:
* 0, do not parse SEI in ucode; 1, parse SEI in ucode
*bit [31:20]: used by ucode for debug purpose
*/
#define NAL_SEARCH_CTL HEVC_ASSIST_SCRATCH_I
/*[31:24] chip feature
31: 0, use MBOX1; 1, use MBOX0
[24:16] debug
0x1, bufmgr only
*/
#define DECODE_MODE HEVC_ASSIST_SCRATCH_J
#define DECODE_STOP_POS HEVC_ASSIST_SCRATCH_K
#define RPM_BUF_SIZE ((RPM_END - RPM_BEGIN) * 2)
#define LMEM_BUF_SIZE (0x600 * 2)
/*
#ifdef MAP_8K
static u32 seg_map_size = 0xd8000;
#else
static u32 seg_map_size = 0x36000;
#endif
*/
//static u32 seg_map_size = 0x36000;
//#define VBH_BUF_COUNT 4
//#define VBH_BUF_SIZE_1080P ((((2 * 16 * 1088) + 0xffff) & (~0xffff)) * VBH_BUF_COUNT)
//#define VBH_BUF_SIZE_4K ((((2 * 16 * 2304) + 0xffff) & (~0xffff))) * VBH_BUF_COUNT)
//#define VBH_BUF_SIZE_8K ((((2 * 16 * 4608) + 0xffff) & (~0xffff))) * VBH_BUF_COUNT)
/*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 aom_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 = 0x0, //0x30000,
},
.sao_vb = {
.buf_size = 0x0, //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,
},
.seg_map = {
// SEGMENT MAP AREA - 1920x1088/4/4 * 3 bits = 0xBF40 Bytes * 16 = 0xBF400
.buf_size = 0xBF400,
},
.daala_top = {
// DAALA TOP STORE AREA - 224 Bytes (use 256 Bytes for LPDDR4) per 128. Total 4096/128*256 = 0x2000
.buf_size = 0xf00,
},
.sao_up = {
// SAO UP STORE AREA - Max 640(10240/16) LCU, each has 16 bytes total 0x2800 bytes
.buf_size = 0x0, //0x2800,
},
.swap_buf = {
// 256cyclex64bit = 2K bytes 0x800 (only 144 cycles valid)
.buf_size = 0x800,
},
.cdf_buf = {
// for context store/load 1024x256 x16 = 512K bytes 16*0x8000
.buf_size = 0x80000,
},
.gmc_buf = {
// for gmc_parameter store/load 128 x 16 = 2K bytes 0x800
.buf_size = 0x800,
},
.scalelut = {
// support up to 32 SCALELUT 1024x32 = 32Kbytes (0x8000)
.buf_size = 0x0, //0x8000,
},
.dblk_para = {
// DBLK -> Max 256(4096/16) LCU, each para 1024bytes(total:0x40000), data 1024bytes(total:0x40000)
.buf_size = 0xd00, /*0xc40*/
},
.dblk_data = {
.buf_size = 0x49000,
},
.cdef_data = {
.buf_size = 0x22400,
},
.ups_data = {
.buf_size = 0x36000,
},
.fgs_table = {
.buf_size = FGS_TABLE_SIZE * FRAME_BUFFERS, // 512x128bits
},
#ifdef AOM_AV1_MMU
.mmu_vbh = {
.buf_size = VBH_BUF_SIZE_1080P, //2*16*(more than 2304)/4, 4K
},
.cm_header = {
#ifdef USE_SPEC_BUF_FOR_MMU_HEAD
.buf_size = MMU_COMPRESS_HEADER_SIZE_1080P * FRAME_BUFFERS, // 0x44000 = ((1088*2*1024*4)/32/4)*(32/8)
#else
.buf_size = 0,
#endif
},
#endif
#ifdef AOM_AV1_MMU_DW
.mmu_vbh_dw = {
.buf_size = DW_VBH_BUF_SIZE_1080P, //2*16*(more than 2304)/4, 4K
},
.cm_header_dw = {
#ifdef USE_SPEC_BUF_FOR_MMU_HEAD
.buf_size = MMU_COMPRESS_HEADER_SIZE_1080P*FRAME_BUFFERS, // 0x44000 = ((1088*2*1024*4)/32/4)*(32/8)
#else
.buf_size = 0,
#endif
},
#endif
.mpred_above = {
.buf_size = 0x2800, /*round from 0x2760*/ /* 2 * size of hw*/
},
#ifdef MV_USE_FIXED_BUF
.mpred_mv = {
.buf_size = MAX_ONE_MV_BUFFER_SIZE_1080P_TM2REVB * FRAME_BUFFERS,/*round from 203A0*/ //1080p, 0x40000 per buffer
},
#endif
.rpm = {
.buf_size = 0x80*2,
},
.lmem = {
.buf_size = 0x400 * 2,
}
},
{
#ifdef VPU_FILMGRAIN_DUMP
.max_width = 640,
.max_height = 480,
#else
.max_width = 4096,
.max_height = 2304,
#endif
.ipp = {
// IPP work space calculation : 4096 * (Y+CbCr+Flags) = 12k, round to 16k
.buf_size = 0x4000,
},
.sao_abv = {
.buf_size = 0x0, //0x30000,
},
.sao_vb = {
.buf_size = 0x0, //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,
},
.seg_map = {
// SEGMENT MAP AREA - 4096x2304/4/4 * 3 bits = 0x36000 Bytes * 16 = 0x360000
.buf_size = 0x360000,
},
.daala_top = {
// DAALA TOP STORE AREA - 224 Bytes (use 256 Bytes for LPDDR4) per 128. Total 4096/128*256 = 0x2000
.buf_size = 0x2000,
},
.sao_up = {
// SAO UP STORE AREA - Max 640(10240/16) LCU, each has 16 bytes total 0x2800 bytes
.buf_size = 0x0, //0x2800,
},
.swap_buf = {
// 256cyclex64bit = 2K bytes 0x800 (only 144 cycles valid)
.buf_size = 0x800,
},
.cdf_buf = {
// for context store/load 1024x256 x16 = 512K bytes 16*0x8000
.buf_size = 0x80000,
},
.gmc_buf = {
// for gmc_parameter store/load 128 x 16 = 2K bytes 0x800
.buf_size = 0x800,
},
.scalelut = {
// support up to 32 SCALELUT 1024x32 = 32Kbytes (0x8000)
.buf_size = 0x0, //0x8000,
},
.dblk_para = {
// DBLK -> Max 256(4096/16) LCU, each para 1024bytes(total:0x40000), data 1024bytes(total:0x40000)
.buf_size = 0x1a00, /*0x1980*/
},
.dblk_data = {
.buf_size = 0x52800,
},
.cdef_data = {
.buf_size = 0x24a00,
},
.ups_data = {
.buf_size = 0x6f000,
},
.fgs_table = {
.buf_size = FGS_TABLE_SIZE * FRAME_BUFFERS, // 512x128bits
},
#ifdef AOM_AV1_MMU
.mmu_vbh = {
.buf_size = VBH_BUF_SIZE_4K, //2*16*(more than 2304)/4, 4K
},
.cm_header = {
#ifdef USE_SPEC_BUF_FOR_MMU_HEAD
.buf_size = MMU_COMPRESS_HEADER_SIZE_4K*FRAME_BUFFERS, // 0x44000 = ((1088*2*1024*4)/32/4)*(32/8)
#else
.buf_size = 0,
#endif
},
#endif
#ifdef AOM_AV1_MMU_DW
.mmu_vbh_dw = {
.buf_size = DW_VBH_BUF_SIZE_4K, //2*16*(more than 2304)/4, 4K
},
.cm_header_dw = {
#ifdef USE_SPEC_BUF_FOR_MMU_HEAD
.buf_size = MMU_COMPRESS_HEADER_SIZE_4K*FRAME_BUFFERS, // 0x44000 = ((1088*2*1024*4)/32/4)*(32/8)
#else
.buf_size = 0,
#endif
},
#endif
.mpred_above = {
.buf_size = 0x5400, /* 2 * size of hw*/
},
#ifdef MV_USE_FIXED_BUF
.mpred_mv = {
/* .buf_size = 0x100000*16,
//4k2k , 0x100000 per buffer */
/* 4096x2304 , 0x120000 per buffer */
.buf_size = MAX_ONE_MV_BUFFER_SIZE_4K_TM2REVB * FRAME_BUFFERS,
},
#endif
.rpm = {
.buf_size = 0x80*2,
},
.lmem = {
.buf_size = 0x400 * 2,
}
},
{
.max_width = 8192,
.max_height = 4608,
.ipp = {
// IPP work space calculation : 4096 * (Y+CbCr+Flags) = 12k, round to 16k
.buf_size = 0x4000,
},
.sao_abv = {
.buf_size = 0x0, //0x30000,
},
.sao_vb = {
.buf_size = 0x0, //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,
},
.seg_map = {
// SEGMENT MAP AREA - 4096x2304/4/4 * 3 bits = 0x36000 Bytes * 16 = 0x360000
.buf_size = 0xd80000,
},
.daala_top = {
// DAALA TOP STORE AREA - 224 Bytes (use 256 Bytes for LPDDR4) per 128. Total 4096/128*256 = 0x2000
.buf_size = 0x2000,
},
.sao_up = {
// SAO UP STORE AREA - Max 640(10240/16) LCU, each has 16 bytes total 0x2800 bytes
.buf_size = 0x0, //0x2800,
},
.swap_buf = {
// 256cyclex64bit = 2K bytes 0x800 (only 144 cycles valid)
.buf_size = 0x800,
},
.cdf_buf = {
// for context store/load 1024x256 x16 = 512K bytes 16*0x8000
.buf_size = 0x80000,
},
.gmc_buf = {
// for gmc_parameter store/load 128 x 16 = 2K bytes 0x800
.buf_size = 0x800,
},
.scalelut = {
// support up to 32 SCALELUT 1024x32 = 32Kbytes (0x8000)
.buf_size = 0x0, //0x8000,
},
.dblk_para = {
// DBLK -> Max 256(4096/16) LCU, each para 1024bytes(total:0x40000), data 1024bytes(total:0x40000)
.buf_size = 0x3300, /*0x32a0*/
},
.dblk_data = {
.buf_size = 0xa4800,
},
.cdef_data = {
.buf_size = 0x29200,
},
.ups_data = {
.buf_size = 0xdb000,
},
.fgs_table = {
.buf_size = FGS_TABLE_SIZE * FRAME_BUFFERS, // 512x128bits
},
#ifdef AOM_AV1_MMU
.mmu_vbh = {
.buf_size = VBH_BUF_SIZE_8K, //2*16*(more than 2304)/4, 4K
},
.cm_header = {
#ifdef USE_SPEC_BUF_FOR_MMU_HEAD
.buf_size = MMU_COMPRESS_HEADER_SIZE_8K*FRAME_BUFFERS, // 0x44000 = ((1088*2*1024*4)/32/4)*(32/8)
#else
.buf_size = 0,
#endif
},
#endif
#ifdef AOM_AV1_MMU_DW
.mmu_vbh_dw = {
.buf_size = DW_VBH_BUF_SIZE_8K, //2*16*(more than 2304)/4, 4K
},
.cm_header_dw = {
#ifdef USE_SPEC_BUF_FOR_MMU_HEAD
.buf_size = MMU_COMPRESS_HEADER_SIZE_8K*FRAME_BUFFERS, // 0x44000 = ((1088*2*1024*4)/32/4)*(32/8)
#else
.buf_size = 0,
#endif
},
#endif
.mpred_above = {
.buf_size = 0xA800, /* 2 * size of hw*/
},
#ifdef MV_USE_FIXED_BUF
.mpred_mv = {
/* .buf_size = 0x100000*16,
//4k2k , 0x100000 per buffer */
/* 4096x2304 , 0x120000 per buffer */
.buf_size = MAX_ONE_MV_BUFFER_SIZE_8K_TM2REVB * FRAME_BUFFERS,
},
#endif
.rpm = {
.buf_size = 0x80*2,
},
.lmem = {
.buf_size = 0x400 * 2,
}
}
};
/*
* AUX DATA Process
*/
static u32 init_aux_size;
static int aux_data_is_avaible(struct AV1HW_s *hw)
{
u32 reg_val;
reg_val = READ_VREG(HEVC_AUX_DATA_SIZE);
if (reg_val != 0 && reg_val != init_aux_size)
return 1;
else
return 0;
}
static void config_aux_buf(struct AV1HW_s *hw)
{
WRITE_VREG(HEVC_AUX_ADR, hw->aux_phy_addr);
init_aux_size = ((hw->prefix_aux_size >> 4) << 16) |
(hw->suffix_aux_size >> 4);
WRITE_VREG(HEVC_AUX_DATA_SIZE, init_aux_size);
}
/*
* dv_meta_flag: 1, dolby meta (T35) only; 2, not include dolby meta (T35)
*/
static void set_aux_data(struct AV1HW_s *hw,
char **aux_data_buf, int *aux_data_size,
unsigned char suffix_flag,
unsigned char dv_meta_flag)
{
int i;
unsigned short *aux_adr;
unsigned int size_reg_val =
READ_VREG(HEVC_AUX_DATA_SIZE);
unsigned int aux_count = 0;
int aux_size = 0;
if (0 == aux_data_is_avaible(hw))
return;
if (hw->aux_data_dirty ||
hw->m_ins_flag == 0) {
hw->aux_data_dirty = 0;
}
if (suffix_flag) {
aux_adr = (unsigned short *)
(hw->aux_addr +
hw->prefix_aux_size);
aux_count =
((size_reg_val & 0xffff) << 4)
>> 1;
aux_size =
hw->suffix_aux_size;
} else {
aux_adr =
(unsigned short *)hw->aux_addr;
aux_count =
((size_reg_val >> 16) << 4)
>> 1;
aux_size =
hw->prefix_aux_size;
}
if (debug & AV1_DEBUG_BUFMGR_MORE) {
av1_print(hw, 0,
"%s:old size %d count %d,suf %d dv_flag %d\r\n",
__func__, *aux_data_size,
aux_count, suffix_flag, dv_meta_flag);
}
if (aux_size > 0 && aux_count > 0) {
int heads_size = 0;
int new_size;
char *new_buf;
for (i = 0; i < aux_count; i++) {
unsigned char tag = aux_adr[i] >> 8;
if (tag != 0 && tag != 0xff) {
if (dv_meta_flag == 0)
heads_size += 8;
else if (dv_meta_flag == 1 && tag == 0x14)
heads_size += 8;
else if (dv_meta_flag == 2 && tag != 0x14)
heads_size += 8;
}
}
new_size = *aux_data_size + aux_count + heads_size;
new_buf = vmalloc(new_size);
if (new_buf) {
unsigned char valid_tag = 0;
unsigned char *h =
new_buf +
*aux_data_size;
unsigned char *p = h + 8;
int len = 0;
int padding_len = 0;
if (*aux_data_buf) {
memcpy(new_buf, *aux_data_buf, *aux_data_size);
vfree(*aux_data_buf);
}
*aux_data_buf = new_buf;
for (i = 0; i < aux_count; i += 4) {
int ii;
unsigned char tag = aux_adr[i + 3] >> 8;
if (tag != 0 && tag != 0xff) {
if (dv_meta_flag == 0)
valid_tag = 1;
else if (dv_meta_flag == 1
&& tag == 0x14)
valid_tag = 1;
else if (dv_meta_flag == 2
&& tag != 0x14)
valid_tag = 1;
else
valid_tag = 0;
if (valid_tag && len > 0) {
*aux_data_size +=
(len + 8);
h[0] = (len >> 24)
& 0xff;
h[1] = (len >> 16)
& 0xff;
h[2] = (len >> 8)
& 0xff;
h[3] = (len >> 0)
& 0xff;
h[6] =
(padding_len >> 8)
& 0xff;
h[7] = (padding_len)
& 0xff;
h += (len + 8);
p += 8;
len = 0;
padding_len = 0;
}
if (valid_tag) {
h[4] = tag;
h[5] = 0;
h[6] = 0;
h[7] = 0;
}
}
if (valid_tag) {
for (ii = 0; ii < 4; ii++) {
unsigned short aa =
aux_adr[i + 3
- ii];
*p = aa & 0xff;
p++;
len++;
if ((aa >> 8) == 0xff)
padding_len++;
}
}
}
if (len > 0) {
*aux_data_size += (len + 8);
h[0] = (len >> 24) & 0xff;
h[1] = (len >> 16) & 0xff;
h[2] = (len >> 8) & 0xff;
h[3] = (len >> 0) & 0xff;
h[6] = (padding_len >> 8) & 0xff;
h[7] = (padding_len) & 0xff;
}
if (debug & AV1_DEBUG_BUFMGR_MORE) {
av1_print(hw, 0,
"aux: (size %d) suffix_flag %d\n",
*aux_data_size, suffix_flag);
for (i = 0; i < *aux_data_size; i++) {
av1_print_cont(hw, 0,
"%02x ", (*aux_data_buf)[i]);
if (((i + 1) & 0xf) == 0)
av1_print_cont(hw, 0, "\n");
}
av1_print_cont(hw, 0, "\n");
}
} else {
av1_print(hw, 0, "new buf alloc failed\n");
if (*aux_data_buf)
vfree(*aux_data_buf);
*aux_data_buf = NULL;
*aux_data_size = 0;
}
}
}
static void set_dv_data(struct AV1HW_s *hw)
{
set_aux_data(hw, &hw->dv_data_buf,
&hw->dv_data_size, 0, 1);
}
static void set_pic_aux_data(struct AV1HW_s *hw,
struct PIC_BUFFER_CONFIG_s *pic, unsigned char suffix_flag,
unsigned char dv_meta_flag)
{
if (pic == NULL)
return;
set_aux_data(hw, &pic->aux_data_buf,
&pic->aux_data_size, suffix_flag, dv_meta_flag);
}
static void copy_dv_data(struct AV1HW_s *hw,
struct PIC_BUFFER_CONFIG_s *pic)
{
char *new_buf;
int new_size;
new_size = pic->aux_data_size + hw->dv_data_size;
new_buf = vmalloc(new_size);
if (new_buf) {
if (debug & AV1_DEBUG_BUFMGR_MORE) {
av1_print(hw, 0,
"%s: (size %d) pic index %d\n",
__func__,
hw->dv_data_size, pic->index);
}
if (pic->aux_data_buf) {
memcpy(new_buf, pic->aux_data_buf, pic->aux_data_size);
vfree(pic->aux_data_buf);
}
memcpy(new_buf + pic->aux_data_size, hw->dv_data_buf, hw->dv_data_size);
pic->aux_data_size += hw->dv_data_size;
pic->aux_data_buf = new_buf;
vfree(hw->dv_data_buf);
hw->dv_data_buf = NULL;
hw->dv_data_size = 0;
}
}
static void release_aux_data(struct AV1HW_s *hw,
struct PIC_BUFFER_CONFIG_s *pic)
{
if (pic->aux_data_buf)
vfree(pic->aux_data_buf);
pic->aux_data_buf = NULL;
pic->aux_data_size = 0;
}
static void dump_aux_buf(struct AV1HW_s *hw)
{
int i;
unsigned short *aux_adr =
(unsigned short *)
hw->aux_addr;
unsigned int aux_size =
(READ_VREG(HEVC_AUX_DATA_SIZE)
>> 16) << 4;
if (hw->prefix_aux_size > 0) {
av1_print(hw, 0,
"prefix aux: (size %d)\n",
aux_size);
for (i = 0; i <
(aux_size >> 1); i++) {
av1_print_cont(hw, 0,
"%04x ",
*(aux_adr + i));
if (((i + 1) & 0xf)
== 0)
av1_print_cont(hw,
0, "\n");
}
}
if (hw->suffix_aux_size > 0) {
aux_adr = (unsigned short *)
(hw->aux_addr +
hw->prefix_aux_size);
aux_size =
(READ_VREG(HEVC_AUX_DATA_SIZE) & 0xffff)
<< 4;
av1_print(hw, 0,
"suffix aux: (size %d)\n",
aux_size);
for (i = 0; i <
(aux_size >> 1); i++) {
av1_print_cont(hw, 0,
"%04x ", *(aux_adr + i));
if (((i + 1) & 0xf) == 0)
av1_print_cont(hw, 0, "\n");
}
}
}
/*
*
*/
/*Losless compression body buffer size 4K per 64x32 (jt)*/
static int compute_losless_comp_body_size(int width, int height,
uint8_t is_bit_depth_10)
{
int width_x64;
int height_x32;
int bsize;
width_x64 = width + 63;
width_x64 >>= 6;
height_x32 = height + 31;
height_x32 >>= 5;
bsize = (is_bit_depth_10?4096:3200)*width_x64*height_x32;
if (debug & AV1_DEBUG_BUFMGR_MORE)
pr_info("%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(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;
if (debug & AV1_DEBUG_BUFMGR_MORE)
pr_info("%s(%d,%d)=>%d\n",
__func__, width, height,
hsize);
return hsize;
}
#ifdef AOM_AV1_MMU_DW
static int compute_losless_comp_body_size_dw(int width, int height,
uint8_t is_bit_depth_10)
{
return compute_losless_comp_body_size(width, height, is_bit_depth_10);
}
/* Losless compression header buffer size 32bytes per 128x64 (jt)*/
static int compute_losless_comp_header_size_dw(int width, int height)
{
return compute_losless_comp_header_size(width, height);
}
#endif
static void init_buff_spec(struct AV1HW_s *hw,
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->vps.buf_start =
buf_spec->short_term_rps.buf_start + buf_spec->short_term_rps.buf_size;
buf_spec->seg_map.buf_start =
buf_spec->vps.buf_start + buf_spec->vps.buf_size;
buf_spec->daala_top.buf_start =
buf_spec->seg_map.buf_start + buf_spec->seg_map.buf_size;
buf_spec->sao_up.buf_start =
buf_spec->daala_top.buf_start + buf_spec->daala_top.buf_size;
buf_spec->swap_buf.buf_start =
buf_spec->sao_up.buf_start + buf_spec->sao_up.buf_size;
buf_spec->cdf_buf.buf_start =
buf_spec->swap_buf.buf_start + buf_spec->swap_buf.buf_size;
buf_spec->gmc_buf.buf_start =
buf_spec->cdf_buf.buf_start + buf_spec->cdf_buf.buf_size;
buf_spec->scalelut.buf_start =
buf_spec->gmc_buf.buf_start + buf_spec->gmc_buf.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->cdef_data.buf_start =
buf_spec->dblk_data.buf_start + buf_spec->dblk_data.buf_size;
buf_spec->ups_data.buf_start =
buf_spec->cdef_data.buf_start + buf_spec->cdef_data.buf_size;
buf_spec->fgs_table.buf_start =
buf_spec->ups_data.buf_start + buf_spec->ups_data.buf_size;
#ifdef AOM_AV1_MMU
buf_spec->mmu_vbh.buf_start =
buf_spec->fgs_table.buf_start + buf_spec->fgs_table.buf_size;
buf_spec->cm_header.buf_start =
buf_spec->mmu_vbh.buf_start + buf_spec->mmu_vbh.buf_size;
#ifdef AOM_AV1_MMU_DW
buf_spec->mmu_vbh_dw.buf_start =
buf_spec->cm_header.buf_start + buf_spec->cm_header.buf_size;
buf_spec->cm_header_dw.buf_start =
buf_spec->mmu_vbh_dw.buf_start + buf_spec->mmu_vbh_dw.buf_size;
buf_spec->mpred_above.buf_start =
buf_spec->cm_header_dw.buf_start + buf_spec->cm_header_dw.buf_size;
#else
buf_spec->mpred_above.buf_start =
buf_spec->cm_header.buf_start + buf_spec->cm_header.buf_size;
#endif
#else
buf_spec->mpred_above.buf_start =
buf_spec->fgs_table.buf_start + buf_spec->fgs_table.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 (!hw)
return;
if (!vdec_secure(hw_to_vdec(hw))) {
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 {
mem_start_virt = codec_mm_vmap(
buf_spec->dblk_para.buf_start,
buf_spec->dblk_para.buf_size);
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);
codec_mm_unmap_phyaddr(mem_start_virt);
} 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("vps.buf_start :%x\n",
buf_spec->vps.buf_start);
pr_info("seg_map.buf_start :%x\n",
buf_spec->seg_map.buf_start);
pr_info("daala_top.buf_start :%x\n",
buf_spec->daala_top.buf_start);
pr_info("swap_buf.buf_start :%x\n",
buf_spec->swap_buf.buf_start);
pr_info("cdf_buf.buf_start :%x\n",
buf_spec->cdf_buf.buf_start);
pr_info("gmc_buf.buf_start :%x\n",
buf_spec->gmc_buf.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("cdef_data.buf_start :%x\n",
buf_spec->cdef_data.buf_start);
pr_info("ups_data.buf_start :%x\n",
buf_spec->ups_data.buf_start);
#ifdef AOM_AV1_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 & AOM_AV1_DEBUG_SEND_PARAM_WITH_REG) == 0) {
pr_info("rpm.buf_start :%x\n",
buf_spec->rpm.buf_start);
}
}
}
static bool v4l_is_there_vframe_bound(struct AV1HW_s *hw)
{
int i;
struct AV1_Common_s *const cm = &hw->common;
struct RefCntBuffer_s *frame_bufs = cm->buffer_pool->frame_bufs;
for (i = 0; i < hw->used_buf_num; ++i) {
if (frame_bufs[i].buf.vframe_bound)
return true;
}
return false;
}
static void v4l_mmu_buffer_release(struct AV1HW_s *hw)
{
struct AV1_Common_s *const cm = &hw->common;
struct RefCntBuffer_s *frame_bufs = cm->buffer_pool->frame_bufs;
int i;
/* release workspace */
if (hw->bmmu_box)
decoder_bmmu_box_free_idx(hw->bmmu_box,
WORK_SPACE_BUF_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
* buffers drivers are released by driver.
*/
for (i = 0; i < hw->used_buf_num; ++i) {
if (!frame_bufs[i].buf.vframe_bound) {
if (hw->bmmu_box)
decoder_bmmu_box_free_idx(hw->bmmu_box,
HEADER_BUFFER_IDX(hw->buffer_wrap[i]));
if (hw->mmu_box)
decoder_mmu_box_free_idx(hw->mmu_box, hw->buffer_wrap[i]);
av1_print(hw, PRINT_FLAG_V4L_DETAIL,
"%s free buffer[%d], bmmu_box: %p, mmu_box: %p\n",
__func__, i, hw->bmmu_box, hw->mmu_box);
}
}
}
static void uninit_mmu_buffers(struct AV1HW_s *hw)
{
#ifndef MV_USE_FIXED_BUF
dealloc_mv_bufs(hw);
#endif
if (hw->is_used_v4l &&
v4l_is_there_vframe_bound(hw)) {
if (get_double_write_mode(hw) != 0x10) {
v4l_mmu_buffer_release(hw);
return;
}
}
if (hw->mmu_box)
decoder_mmu_box_free(hw->mmu_box);
hw->mmu_box = NULL;
#ifdef AOM_AV1_MMU_DW
if (hw->mmu_box_dw)
decoder_mmu_box_free(hw->mmu_box_dw);
hw->mmu_box_dw = NULL;
#endif
if (hw->bmmu_box)
decoder_bmmu_box_free(hw->bmmu_box);
hw->bmmu_box = NULL;
}
static int calc_luc_quantity(int lcu_size, u32 w, u32 h)
{
int pic_width_64 = (w + 63) & (~0x3f);
int pic_height_32 = (h + 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;
return pic_width_lcu * pic_height_lcu;
}
static int v4l_alloc_and_config_pic(struct AV1HW_s *hw,
struct PIC_BUFFER_CONFIG_s *pic)
{
int ret = -1;
int i = pic->index;
int dw_mode = get_double_write_mode_init(hw);
int lcu_total = calc_luc_quantity(hw->current_lcu_size,
hw->frame_width, hw->frame_height);
#ifdef MV_USE_FIXED_BUF
u32 mpred_mv_end = hw->work_space_buf->mpred_mv.buf_start +
hw->work_space_buf->mpred_mv.buf_size;
//#ifdef USE_DYNAMIC_MV_BUFFER
// int32_t MV_MEM_UNIT = (lcu_size == 128) ? (19*4*16) : (19*16);
// int32_t mv_buffer_size = (lcu_total*MV_MEM_UNIT);
//#else
int32_t mv_buffer_size = hw->max_one_mv_buffer_size;
//#endif
#endif
struct vdec_v4l2_buffer *fb = NULL;
if (i < 0)
return ret;
ret = vdec_v4l_get_buffer(hw->v4l2_ctx, &fb);
if (ret < 0) {
av1_print(hw, 0, "[%d] AV1 get buffer fail.\n",
((struct aml_vcodec_ctx *) (hw->v4l2_ctx))->id);
return ret;
}
if (hw->mmu_enable) {
hw->m_BUF[i].header_addr = decoder_bmmu_box_get_phy_addr(
hw->bmmu_box, HEADER_BUFFER_IDX(hw->buffer_wrap[i]));
if (debug & AV1_DEBUG_BUFMGR_MORE) {
pr_info("MMU header_adr %d: %ld\n",
i, hw->m_BUF[i].header_addr);
}
}
#ifdef MV_USE_FIXED_BUF
if ((hw->work_space_buf->mpred_mv.buf_start +
((i + 1) * mv_buffer_size))
<= mpred_mv_end) {
#endif
hw->m_BUF[i].v4l_ref_buf_addr = (ulong)fb;
pic->cma_alloc_addr = fb->m.mem[0].addr;
if (fb->num_planes == 1) {
hw->m_BUF[i].start_adr = fb->m.mem[0].addr;
hw->m_BUF[i].luma_size = fb->m.mem[0].offset;
hw->m_BUF[i].size = fb->m.mem[0].size;
fb->m.mem[0].bytes_used = fb->m.mem[0].size;
pic->dw_y_adr = hw->m_BUF[i].start_adr;
pic->dw_u_v_adr = pic->dw_y_adr + hw->m_BUF[i].luma_size;
} else if (fb->num_planes == 2) {
hw->m_BUF[i].start_adr = fb->m.mem[0].addr;
hw->m_BUF[i].size = fb->m.mem[0].size;
hw->m_BUF[i].chroma_addr = fb->m.mem[1].addr;
hw->m_BUF[i].chroma_size = fb->m.mem[1].size;
fb->m.mem[0].bytes_used = fb->m.mem[0].size;
fb->m.mem[1].bytes_used = fb->m.mem[1].size;
pic->dw_y_adr = hw->m_BUF[i].start_adr;
pic->dw_u_v_adr = hw->m_BUF[i].chroma_addr;
}
/* config frame buffer */
if (hw->mmu_enable)
pic->header_adr = hw->m_BUF[i].header_addr;
pic->BUF_index = i;
pic->lcu_total = lcu_total;
pic->mc_canvas_y = pic->index;
pic->mc_canvas_u_v = pic->index;
if (dw_mode & 0x10) {
pic->mc_canvas_y = (pic->index << 1);
pic->mc_canvas_u_v = (pic->index << 1) + 1;
}
#ifdef MV_USE_FIXED_BUF
pic->mpred_mv_wr_start_addr =
hw->work_space_buf->mpred_mv.buf_start +
(pic->index * mv_buffer_size);
#endif
#ifdef DUMP_FILMGRAIN
if (pic->index == fg_dump_index) {
pic->fgs_table_adr = hw->fg_phy_addr;
pr_info("set buffer %d film grain table 0x%x\n",
pic->index, pic->fgs_table_adr);
} else
#endif
pic->fgs_table_adr =
hw->work_space_buf->fgs_table.buf_start +
(pic->index * FGS_TABLE_SIZE);
if (debug) {
pr_info("%s index %d BUF_index %d ",
__func__, pic->index,
pic->BUF_index);
pr_info("comp_body_size %x comp_buf_size %x ",
pic->comp_body_size,
pic->buf_size);
pr_info("mpred_mv_wr_start_adr %d\n",
pic->mpred_mv_wr_start_addr);
pr_info("dw_y_adr %d, pic_config->dw_u_v_adr =%d\n",
pic->dw_y_adr,
pic->dw_u_v_adr);
}
#ifdef MV_USE_FIXED_BUF
}
#endif
return ret;
}
static int config_pic(struct AV1HW_s *hw,
struct PIC_BUFFER_CONFIG_s *pic_config)
{
int ret = -1;
int i;
int pic_width = hw->init_pic_w;
int pic_height = hw->init_pic_h;
//int lcu_size = ((params->p.seq_flags >> 6) & 0x1) ? 128 : 64;
int lcu_size = hw->current_lcu_size;
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;
#ifdef MV_USE_FIXED_BUF
u32 mpred_mv_end = hw->work_space_buf->mpred_mv.buf_start +
hw->work_space_buf->mpred_mv.buf_size;
//#ifdef USE_DYNAMIC_MV_BUFFER
// int32_t MV_MEM_UNIT = (lcu_size == 128) ? (19*4*16) : (19*16);
// int32_t mv_buffer_size = (lcu_total*MV_MEM_UNIT);
//#else
int32_t mv_buffer_size = hw->max_one_mv_buffer_size;
//#endif
#endif
u32 y_adr = 0;
int buf_size = 0;
int losless_comp_header_size =
compute_losless_comp_header_size(pic_width,
pic_height);
int losless_comp_body_size = compute_losless_comp_body_size(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(hw);
hw->lcu_total = lcu_total;
if (dw_mode && (dw_mode & 0x20) == 0) {
int pic_width_dw = pic_width /
get_double_write_ratio(hw, dw_mode);
int pic_height_dw = pic_height /
get_double_write_ratio(hw, 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;
if ((!hw->mmu_enable) && ((dw_mode & 0x10) == 0))
buf_size += (mc_buffer_size_h << 16);
#ifdef USE_SPEC_BUF_FOR_MMU_HEAD
if (hw->mmu_enable) {
pic_config->header_adr =
hw->work_space_buf->cm_header.buf_start +
(pic_config->index * vav1_mmu_compress_header_size(hw));
#ifdef AOM_AV1_MMU_DW
if (hw->dw_mmu_enable) {
pic_config->header_dw_adr =
hw->work_space_buf->cm_header_dw.buf_start +
(pic_config->index * vav1_mmu_compress_header_size(hw));
}
#endif
}
#else
/*!USE_SPEC_BUF_FOR_MMU_HEAD*/
if (hw->mmu_enable) {
pic_config->header_adr = decoder_bmmu_box_get_phy_addr(
hw->bmmu_box, HEADER_BUFFER_IDX(hw->buffer_wrap[pic_config->index]));
#ifdef AOM_AV1_MMU_DW
if (hw->dw_mmu_enable) {
pic_config->header_dw_adr = decoder_bmmu_box_get_phy_addr(
hw->bmmu_box, DW_HEADER_BUFFER_IDX(hw->buffer_wrap[pic_config->index]));
}
if (debug & AV1_DEBUG_BUFMGR_MORE) {
pr_info("MMU dw header_adr (%d, %d) %d: %d\n",
hw->dw_mmu_enable,
DW_HEADER_BUFFER_IDX(hw->buffer_wrap[pic_config->index]),
hw->buffer_wrap[pic_config->index],
pic_config->header_dw_adr);
}
#endif
if (debug & AV1_DEBUG_BUFMGR_MORE) {
pr_info("MMU header_adr %d: %d\n",
hw->buffer_wrap[pic_config->index], pic_config->header_adr);
}
}
#endif
i = pic_config->index;
#ifdef MV_USE_FIXED_BUF
if ((hw->work_space_buf->mpred_mv.buf_start +
((i + 1) * mv_buffer_size))
<= mpred_mv_end
) {
#endif
if (buf_size > 0) {
ret = decoder_bmmu_box_alloc_buf_phy(hw->bmmu_box,
VF_BUFFER_IDX(hw->buffer_wrap[i]),
buf_size, DRIVER_NAME,
&pic_config->cma_alloc_addr);
if (ret < 0) {
pr_info(
"decoder_bmmu_box_alloc_buf_phy idx %d size %d fail\n",
VF_BUFFER_IDX(hw->buffer_wrap[i]),
buf_size
);
return ret;
}
if (pic_config->cma_alloc_addr)
y_adr = pic_config->cma_alloc_addr;
else {
pr_info(
"decoder_bmmu_box_alloc_buf_phy idx %d size %d return null\n",
VF_BUFFER_IDX(hw->buffer_wrap[i]),
buf_size
);
return -1;
}
}
{
/*ensure get_pic_by_POC()
not get the buffer not decoded*/
pic_config->BUF_index = i;
pic_config->lcu_total = lcu_total;
pic_config->comp_body_size = losless_comp_body_size;
pic_config->buf_size = buf_size;
pic_config->mc_canvas_y = pic_config->index;
pic_config->mc_canvas_u_v = pic_config->index;
if