| /* |
| * 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 (dw_mode & 0x10) { |