vdec: h265 alloc mmu_box when dw changed from 0x10 to 0x1 [1/1]
authorapollo.ling <apollo.ling@amlogic.com>
Wed, 22 Jul 2020 02:47:08 +0000 (10:47 +0800)
committerHui Zhang <hui.zhang@amlogic.com>
Tue, 28 Jul 2020 07:03:28 +0000 (00:03 -0700)
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 <apollo.ling@amlogic.com>
drivers/frame_provider/decoder/h265/vh265.c

index 886d879922b723d14f0ead63a978ef58d1ebf3e8..e9970ffdd38649fe41cd5b76aefd35a6b1c69eac 100644 (file)
@@ -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) {