From ba3ab96fd7ce1cf012b2935a13adc94927d63568 Mon Sep 17 00:00:00 2001 From: "apollo.ling" Date: Wed, 22 Jul 2020 10:47:08 +0800 Subject: [PATCH] vdec: h265 alloc mmu_box when dw changed from 0x10 to 0x1 [1/1] PD#SWPL-28883 Problem: When h265 dw changed from 0x10 to 1, mmu_box is NULL,can not play video Solution: 1. When h265 dw changes to 1, check and alloc mmu_box 2. add calling vm_unmap_aliases() every 64 times because vfree is not synchronize. Verify: ac214 Change-Id: I0c8920debf79a0af2fafaca07b5bc20e8467adab Signed-off-by: apollo.ling --- drivers/frame_provider/decoder/h265/vh265.c | 56 ++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/drivers/frame_provider/decoder/h265/vh265.c b/drivers/frame_provider/decoder/h265/vh265.c index 886d879..e9970ff 100644 --- a/drivers/frame_provider/decoder/h265/vh265.c +++ b/drivers/frame_provider/decoder/h265/vh265.c @@ -2832,6 +2832,42 @@ static void uninit_mmu_buffers(struct hevc_state_s *hevc) decoder_bmmu_box_free(hevc->bmmu_box); hevc->bmmu_box = NULL; } + +static int init_mmu_box(struct hevc_state_s *hevc) +{ + int tvp_flag = vdec_secure(hw_to_vdec(hevc)) ? + CODEC_MM_FLAGS_TVP : 0; + int buf_size = 64; + + if ((hevc->max_pic_w * hevc->max_pic_h) > 0 && + (hevc->max_pic_w * hevc->max_pic_h) <= 1920*1088) { + buf_size = 24; + } + + if (get_dbg_flag(hevc)) { + hevc_print(hevc, 0, "%s max_w %d max_h %d\n", + __func__, hevc->max_pic_w, hevc->max_pic_h); + } + + hevc->need_cache_size = buf_size * SZ_1M; + hevc->sc_start_time = get_jiffies_64(); + if (hevc->mmu_enable + && ((get_double_write_mode(hevc) & 0x10) == 0)) { + hevc->mmu_box = decoder_mmu_box_alloc_box(DRIVER_NAME, + hevc->index, + MAX_REF_PIC_NUM, + buf_size * SZ_1M, + tvp_flag + ); + if (!hevc->mmu_box) { + hevc_print(hevc, 0, "h265 alloc mmu box failed!!\n"); + return -1; + } + } + + return 0; +} + static int init_mmu_buffers(struct hevc_state_s *hevc) { int tvp_flag = vdec_secure(hw_to_vdec(hevc)) ? @@ -4779,6 +4815,7 @@ static void decoder_hw_reset(void) { int i; unsigned int data32; + /* reset iqit to start mem init again */ WRITE_VREG(DOS_SW_RESET3, (1 << 14) ); @@ -4872,6 +4909,7 @@ static void decoder_hw_reset(void) WRITE_VREG(HEVCD_IPP_TOP_CNTL, (1 << 1) | /* enable ipp */ (0 << 0) /* software reset ipp and mpp */ ); + } #ifdef CONFIG_HEVC_CLK_FORCED_ON @@ -6168,8 +6206,11 @@ static void set_aux_data(struct hevc_state_s *hevc, static void release_aux_data(struct hevc_state_s *hevc, struct PIC_s *pic) { - if (pic->aux_data_buf) + if (pic->aux_data_buf) { vfree(pic->aux_data_buf); + if ((run_count[hevc->index] & 63) == 0) + vm_unmap_aliases(); + } pic->aux_data_buf = NULL; pic->aux_data_size = 0; } @@ -10673,6 +10714,16 @@ force_output: "interlace (%d, %d), profile_etc %x, ar 0x%x, dw %d\n", hevc->pic_w, hevc->pic_h, hevc->param.p.profile_etc, hevc->frame_ar, get_double_write_mode(hevc)); + /* When dw changed from 0x10 to 1, the mmu_box is NULL */ + if (!hevc->mmu_box && init_mmu_box(hevc) != 0) { + hevc->dec_result = DEC_RESULT_FORCE_EXIT; + hevc->fatal_error |= + DECODER_FATAL_ERROR_NO_MEM; + vdec_schedule_work(&hevc->work); + hevc_print(hevc, + 0, "can not alloc mmu box, force exit\n"); + return IRQ_HANDLED; + } } #ifdef MULTI_INSTANCE_SUPPORT if (hevc->m_ins_flag) { @@ -12624,6 +12675,9 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) else if (step == 0x11) step = 0x12; + if (hevc->fatal_error & DECODER_FATAL_ERROR_NO_MEM) + return 0; + if (hevc->eos) return 0; if (!hevc->first_sc_checked && hevc->mmu_enable) { -- 2.20.1