116 files changed, 25845 insertions, 36303 deletions
diff --git a/drivers/frame_provider/decoder/h264_multi/vmh264.c b/drivers/frame_provider/decoder/h264_multi/vmh264.c index c2e0e91..91d8c1f 100644 --- a/drivers/frame_provider/decoder/h264_multi/vmh264.c +++ b/drivers/frame_provider/decoder/h264_multi/vmh264.c @@ -63,6 +63,9 @@ #include <linux/crc32.h> #include <media/v4l2-mem2mem.h> +#define DETECT_WRONG_MULTI_SLICE + + #undef pr_info #define pr_info printk #define VDEC_DW @@ -131,6 +134,8 @@ unsigned int h264_debug_mask = 0xff; */ unsigned int h264_debug_cmd; +static int ref_b_frame_error_max_count = 50; + static unsigned int dec_control = DEC_CONTROL_FLAG_FORCE_2997_1080P_INTERLACE | DEC_CONTROL_FLAG_FORCE_2500_576P_INTERLACE; @@ -267,8 +272,13 @@ static unsigned int i_only_flag; bit[12] i_only when error happen bit[13] 0: mark error according to last pic, 1: ignore mark error bit[14] 0: result done when timeout from ucode. 1: reset bufmgr when timeout. + bit[15] 1: dpb_frame_count If the dpb_frame_count difference is large, it moves out of the DPB buffer. + bit[16] 1: check slice header number. + bit[17] 1: If the decoded Mb count is insufficient but greater than the threshold, it is considered the correct frame. + bit[18] 1: time out status, store pic to dpb buffer. + bit[19] 1: If a lot b frames are wrong consecutively, the DPB queue reset. */ -static unsigned int error_proc_policy = 0x4fb6; /*0x1f14*/ +static unsigned int error_proc_policy = 0xfCfb6; /*0x1f14*/ /* @@ -306,6 +316,9 @@ static unsigned int frmbase_cont_bitlevel = 0x40; static unsigned int frmbase_cont_bitlevel2 = 0x1; +static unsigned int check_slice_num = 30; + +static unsigned int mb_count_threshold = 5; /*percentage*/ #define MH264_USERDATA_ENABLE @@ -633,8 +646,8 @@ struct vdec_h264_hw_s { #endif struct StorablePicture *last_dec_picture; - ulong lmem_addr; - dma_addr_t lmem_addr_remap; + ulong lmem_phy_addr; + dma_addr_t lmem_addr; void *bmmu_box; #ifdef H264_MMU @@ -846,10 +859,26 @@ struct vdec_h264_hw_s { bool first_head_check_flag; unsigned int height_aspect_ratio; unsigned int width_aspect_ratio; - bool new_iframe_flag; - bool ref_err_flush_dpb_flag; unsigned int first_i_policy; u32 reorder_dpb_size_margin; + bool wait_reset_done_flag; +#ifdef DETECT_WRONG_MULTI_SLICE + unsigned int multi_slice_pic_check_count; + /* multi_slice_pic_flag: + 0, unknown; + 1, single slice; + 2, multi slice + */ + unsigned int multi_slice_pic_flag; + unsigned int picture_slice_count; + unsigned int cur_picture_slice_count; + unsigned char force_slice_as_picture_flag; + unsigned int last_picture_slice_count; + unsigned int first_pre_frame_num; +#endif + unsigned int res_ch_flag; + u32 b_frame_error_count; + struct vdec_info gvs; }; static u32 again_threshold; @@ -902,13 +931,11 @@ static void h264_clear_dpb(struct vdec_h264_hw_s *hw); /* 0:linear 1:32x32 2:64x32 ; m8baby test1902 */ static u32 mem_map_mode = H265_MEM_MAP_MODE; -#define MAX_SIZE_8K (8192 * 4608) #define MAX_SIZE_4K (4096 * 2304) 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; + int max = MAX_SIZE_4K; if (w < 0 || h < 0) return true; @@ -1669,6 +1696,7 @@ static unsigned char is_buf_spec_in_disp_q(struct vdec_h264_hw_s *hw, static int alloc_one_buf_spec(struct vdec_h264_hw_s *hw, int i) { + struct vdec_s *vdec = hw_to_vdec(hw); if (hw->mmu_enable) { if (hw->buffer_spec[i].alloc_header_addr) return 0; @@ -1706,7 +1734,25 @@ static int alloc_one_buf_spec(struct vdec_h264_hw_s *hw, int i) hw->no_mem_count = 0; hw->stat &= ~DECODER_FATAL_ERROR_NO_MEM; } - + if (!vdec_secure(vdec)) { + /*init internal buf*/ + char *tmpbuf = (char *)codec_mm_phys_to_virt(hw->buffer_spec[i].cma_alloc_addr); + if (tmpbuf) { + memset(tmpbuf, 0, PAGE_ALIGN(buf_size)); + codec_mm_dma_flush(tmpbuf, + PAGE_ALIGN(buf_size), + DMA_TO_DEVICE); + } else { + tmpbuf = codec_mm_vmap(hw->buffer_spec[i].cma_alloc_addr, PAGE_ALIGN(buf_size)); + if (tmpbuf) { + memset(tmpbuf, 0, PAGE_ALIGN(buf_size)); + codec_mm_dma_flush(tmpbuf, + PAGE_ALIGN(buf_size), + DMA_TO_DEVICE); + codec_mm_unmap_phyaddr(tmpbuf); + } + } + } hw->buffer_spec[i].buf_adr = hw->buffer_spec[i].cma_alloc_addr; addr = hw->buffer_spec[i].buf_adr; @@ -2513,6 +2559,7 @@ static int check_force_interlace(struct vdec_h264_hw_s *hw, static void fill_frame_info(struct vdec_h264_hw_s *hw, struct FrameStore *frame) { struct vframe_qos_s *vframe_qos = &hw->vframe_qos; + if (frame->slice_type == I_SLICE) vframe_qos->type = 1; else if (frame->slice_type == P_SLICE) @@ -2520,7 +2567,10 @@ static void fill_frame_info(struct vdec_h264_hw_s *hw, struct FrameStore *frame) else if (frame->slice_type == B_SLICE) vframe_qos->type = 3; - vframe_qos->size = frame->frame_size; + if (input_frame_based(hw_to_vdec(hw))) + vframe_qos->size = frame->frame_size2; + else + vframe_qos->size = frame->frame_size; vframe_qos->pts = frame->pts64; vframe_qos->max_mv = frame->max_mv; @@ -2553,8 +2603,6 @@ static void fill_frame_info(struct vdec_h264_hw_s *hw, struct FrameStore *frame) vframe_qos->min_skip); */ vframe_qos->num++; - if (hw->frameinfo_enable) - vdec_fill_frame_info(vframe_qos, 1); } static int is_iframe(struct FrameStore *frame) { @@ -2572,6 +2620,8 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; struct vframe_s *vf = NULL; int buffer_index = frame->buf_spec_num; + struct aml_vcodec_ctx * v4l2_ctx = hw->v4l2_ctx; + ulong nv_order = VIDTYPE_VIU_NV21; int vf_count = 1; int i; int bForceInterlace = 0; @@ -2582,6 +2632,14 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) __func__, buffer_index); return -1; } + + /* swap uv */ + if (hw->is_used_v4l) { + if ((v4l2_ctx->cap_pix_fmt == V4L2_PIX_FMT_NV12) || + (v4l2_ctx->cap_pix_fmt == V4L2_PIX_FMT_NV12M)) + nv_order = VIDTYPE_VIU_NV12; + } + if (force_disp_bufspec_num & 0x100) { /*recycle directly*/ if (hw->buffer_spec[frame->buf_spec_num].used != 3 && @@ -2631,6 +2689,40 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) hw->last_pts64 = frame->pts64; hw->last_pts = frame->pts; } + + /* SWPL-18973 96000/15=6400, less than 15fps check */ + if ((!hw->duration_from_pts_done) && (hw->frame_dur > 6400ULL)) { + if ((check_force_interlace(hw, frame)) && + (frame->slice_type == I_SLICE) && + (hw->pts_outside)) { + if ((!hw->h264_pts_count) || (!hw->h264pts1)) { + hw->h264pts1 = frame->pts; + hw->h264_pts_count = 0; + } else if (frame->pts > hw->h264pts1) { + u32 calc_dur = + PTS2DUR(frame->pts - hw->h264pts1); + calc_dur = ((calc_dur/hw->h264_pts_count) << 1); + if (hw->frame_dur < (calc_dur + 200) && + hw->frame_dur > (calc_dur - 200)) { + hw->frame_dur >>= 1; + vdec_schedule_work(&hw->notify_work); + dpb_print(DECODE_ID(hw), 0, + "correct frame_dur %d, calc_dur %d, count %d\n", + hw->frame_dur, (calc_dur >> 1), hw->h264_pts_count); + hw->duration_from_pts_done = 1; + hw->h264_pts_count = 0; + } + } + } + hw->h264_pts_count++; + } + + if (frame->data_flag & ERROR_FLAG) { + vdec_count_info(&hw->gvs, 1, 0); + if (!hw->send_error_frame_flag) + hw->gvs.drop_frame_count++; + } + if ((frame->data_flag & NODISP_FLAG) || (frame->data_flag & NULL_FLAG) || ((!hw->send_error_frame_flag) && @@ -2666,6 +2758,8 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) bForceInterlace = check_force_interlace(hw, frame); if (bForceInterlace) vf_count = 2; + if (hw->is_used_v4l) + vf_count = 1; hw->buffer_spec[buffer_index].vf_ref = 0; fill_frame_info(hw, frame); for (i = 0; i < vf_count; i++) { @@ -2713,7 +2807,7 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) if (hw->double_write_mode) { vf->type |= VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; - vf->type |= VIDTYPE_VIU_NV21; + vf->type |= nv_order; if (hw->double_write_mode == 3) vf->type |= VIDTYPE_COMPRESS; @@ -2746,7 +2840,7 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) vf->compHeight = hw->frame_height; } else { vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD | - VIDTYPE_VIU_NV21; + nv_order; vf->canvas0Addr = vf->canvas1Addr = spec2canvas(&hw->buffer_spec[buffer_index]); @@ -2778,12 +2872,23 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) if (bForceInterlace || is_interlace(frame)) { vf->type = VIDTYPE_INTERLACE_FIRST | - VIDTYPE_VIU_NV21; + nv_order; if (bForceInterlace) { + if (frame->frame != NULL && frame->frame->pic_struct == PIC_TOP_BOT) { vf->type |= (i == 0 ? VIDTYPE_INTERLACE_TOP : VIDTYPE_INTERLACE_BOTTOM); + } else if (frame->frame != NULL && frame->frame->pic_struct == PIC_BOT_TOP) { + vf->type |= (i == 0 ? + VIDTYPE_INTERLACE_BOTTOM : + VIDTYPE_INTERLACE_TOP); + } else { + vf->type |= (i == 0 ? + VIDTYPE_INTERLACE_TOP : + VIDTYPE_INTERLACE_BOTTOM); + } + if (i == 1) { vf->pts = 0; vf->pts_us64 = 0; @@ -2800,8 +2905,16 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) vf->duration = vf->duration/2; } - if (i == 0) - decoder_do_frame_check(hw_to_vdec(hw), vf); + if (i == 0) { + struct vdec_s *pvdec; + struct vdec_info vs; + + pvdec = hw_to_vdec(hw); + memset(&vs, 0, sizeof(struct vdec_info)); + pvdec->dec_status(pvdec, &vs); + decoder_do_frame_check(pvdec, vf); + vdec_fill_vdec_frame(pvdec, &hw->vframe_qos, &vs, vf, frame->hw_decode_time); + } /*vf->ratio_control |= (0x3FF << DISP_RATIO_ASPECT_RATIO_BIT);*/ vf->sar_width = hw->width_aspect_ratio; @@ -3211,7 +3324,7 @@ int config_decode_buf(struct vdec_h264_hw_s *hw, struct StorablePicture *pic) * bit 1:0 -- h264_co_mb_info_wr_ptr */ #define H264_CO_MB_RW_CTL VLD_C3D /* 0xc3d */ - +#define DCAC_DDR_BYTE64_CTL 0x0e1d unsigned long canvas_adr; unsigned int ref_reg_val; unsigned int one_ref_cfg = 0; @@ -3313,9 +3426,14 @@ int config_decode_buf(struct vdec_h264_hw_s *hw, struct StorablePicture *pic) h264_buffer_info_data_write_count = 0; //disable this read cache when frame width <= 64 (4MBs) - //IQIDCT_CONTROL, bit[16] – dcac_dma_read_cache_disable - if (hw->frame_width <= 64) + //IQIDCT_CONTROL, bit[16] dcac_dma_read_cache_disable + if (hw->frame_width <= 64) { SET_VREG_MASK(IQIDCT_CONTROL,(1 << 16)); + if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A)) + // Disable DDR_BYTE64_CACHE + WRITE_VREG(DCAC_DDR_BYTE64_CTL, + (READ_VREG(DCAC_DDR_BYTE64_CTL) & (~0xf)) | 0xa); + } else CLEAR_VREG_MASK(IQIDCT_CONTROL,(1 << 16)); @@ -3352,6 +3470,24 @@ int config_decode_buf(struct vdec_h264_hw_s *hw, struct StorablePicture *pic) pic->data_flag |= ERROR_FLAG; dpb_print(DECODE_ID(hw), PRINT_FLAG_ERRORFLAG_DBG, " ref error mark1 \n"); } + + if (error_proc_policy & 0x80000) { + if (ref_b_frame_error_max_count && + ref->slice_type == B_SLICE) { + if (ref->data_flag & ERROR_FLAG) + hw->b_frame_error_count++; + else + hw->b_frame_error_count = 0; + if (hw->b_frame_error_count > ref_b_frame_error_max_count) { + hw->b_frame_error_count = 0; + dpb_print(DECODE_ID(hw), 0, + "error %d B frame, reset dpb buffer\n", + ref_b_frame_error_max_count); + return -1; + } + } + } + if (ref->data_flag & NULL_FLAG) hw->data_flag |= NULL_FLAG; #endif @@ -3736,10 +3872,19 @@ static struct vframe_s *vh264_vf_get(void *op_arg) struct vframe_s *vf; struct vdec_s *vdec = op_arg; struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; + struct aml_vcodec_ctx * v4l2_ctx = hw->v4l2_ctx; + ulong nv_order = VIDTYPE_VIU_NV21; if (!hw) return NULL; + /* swap uv */ + if (hw->is_used_v4l) { + if ((v4l2_ctx->cap_pix_fmt == V4L2_PIX_FMT_NV12) || + (v4l2_ctx->cap_pix_fmt == V4L2_PIX_FMT_NV12M)) + nv_order = VIDTYPE_VIU_NV12; + } + if (force_disp_bufspec_num & 0x100) { int buffer_index = force_disp_bufspec_num & 0xff; if (force_disp_bufspec_num & 0x200) @@ -3770,7 +3915,7 @@ static struct vframe_s *vh264_vf_get(void *op_arg) if (hw->double_write_mode) { vf->type |= VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; - vf->type |= VIDTYPE_VIU_NV21; + vf->type |= nv_order; if (hw->double_write_mode == 3) vf->type |= VIDTYPE_COMPRESS; @@ -3808,7 +3953,7 @@ static struct vframe_s *vh264_vf_get(void *op_arg) } } else { vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD | - VIDTYPE_VIU_NV21; + nv_order; vf->canvas0Addr = vf->canvas1Addr = spec2canvas(&hw->buffer_spec[buffer_index]); } @@ -3862,6 +4007,24 @@ static struct vframe_s *vh264_vf_get(void *op_arg) return NULL; } +static bool vf_valid_check(struct vframe_s *vf, struct vdec_h264_hw_s *hw) { + int i,j; + if (hw->is_used_v4l) + return true; + for (i = 0; i < VF_POOL_SIZE; i++) { + for (j = 0; j < VF_POOL_NUM; j ++) { + if (vf == &(hw->vfpool[j][i])) + return true; + } + } + dpb_print(DECODE_ID(hw), 0, " invalid vf been put, vf = %p\n", vf); + for (i = 0; i < VF_POOL_SIZE; i++) { + dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, + "dump vf [%d]= %p\n", i, &(hw->vfpool[hw->cur_pool][i])); + } + return false; +} + static void vh264_vf_put(struct vframe_s *vf, void *op_arg) { struct vdec_s *vdec = op_arg; @@ -3925,7 +4088,8 @@ static void vh264_vf_put(struct vframe_s *vf, void *op_arg) spin_unlock_irqrestore(&hw->bufspec_lock, flags); hw->vf_put_count++; - kfifo_put(&hw->newframe_q, (const struct vframe_s *)vf); + if (vf && (vf_valid_check(vf, hw) == true)) + kfifo_put(&hw->newframe_q, (const struct vframe_s *)vf); #define ASSIST_MBOX1_IRQ_REG VDEC_ASSIST_MBOX1_IRQ_REG if (hw->buffer_empty_flag) @@ -4378,55 +4542,55 @@ static void get_picture_qos_info(struct StorablePicture *picture) #endif picture->min_mv = mv_lo; +#ifdef DEBUG_QOS /* {mvy_L0_max, mvy_L0_min} */ rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); mv_hi = (rdata32>>16)&0xffff; if (mv_hi & 0x8000) mv_hi = 0x8000 - mv_hi; -#ifdef DEBUG_QOS pr_info(" [Picture %d Quality] MVY_L0 MAX : %d\n", pic_number, mv_hi); -#endif + mv_lo = (rdata32>>0)&0xffff; if (mv_lo & 0x8000) mv_lo = 0x8000 - mv_lo; -#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVY_L0 MIN : %d\n", pic_number, mv_lo); -#endif + /* {mvx_L1_max, mvx_L1_min} */ rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); mv_hi = (rdata32>>16)&0xffff; if (mv_hi & 0x8000) mv_hi = 0x8000 - mv_hi; -#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVX_L1 MAX : %d\n", pic_number, mv_hi); -#endif + mv_lo = (rdata32>>0)&0xffff; if (mv_lo & 0x8000) mv_lo = 0x8000 - mv_lo; -#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVX_L1 MIN : %d\n", pic_number, mv_lo); -#endif + /* {mvy_L1_max, mvy_L1_min} */ rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); mv_hi = (rdata32>>16)&0xffff; if (mv_hi & 0x8000) mv_hi = 0x8000 - mv_hi; -#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVY_L1 MAX : %d\n", pic_number, mv_hi); -#endif + mv_lo = (rdata32>>0)&0xffff; if (mv_lo & 0x8000) mv_lo = 0x8000 - mv_lo; -#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVY_L1 MIN : %d\n", pic_number, mv_lo); #endif @@ -5339,6 +5503,8 @@ static int parse_one_sei_record(struct vdec_h264_hw_s *hw, /* user data length should be align with 8 bytes, if not, then padding with zero*/ for (i = 0; i < payload_size; i += 8) { + if (hw->sei_itu_data_len + i >= SEI_ITU_DATA_SIZE) + break; // Avoid out-of-bound writing for (j = 0; j < 8; j++) { int index; @@ -5356,6 +5522,8 @@ static int parse_one_sei_record(struct vdec_h264_hw_s *hw, data_len = ((payload_size + 8) >> 3) << 3; hw->sei_itu_data_len += data_len; + if (hw->sei_itu_data_len >= SEI_ITU_DATA_SIZE) + hw->sei_itu_data_len = SEI_ITU_DATA_SIZE; /* dpb_print(DECODE_ID(hw), 0, "%s: user data, and len = %d:\n", @@ -5408,16 +5576,22 @@ static void check_decoded_pic_error(struct vdec_h264_hw_s *hw) return; if (get_cur_slice_picture_struct(p_H264_Dpb) != FRAME) mb_total /= 2; - if (error_proc_policy & 0x100) { - if (decode_mb_count < mb_total) - p->data_flag |= ERROR_FLAG; - } if ((error_proc_policy & 0x200) && READ_VREG(ERROR_STATUS_REG) != 0) { p->data_flag |= ERROR_FLAG; } + if (error_proc_policy & 0x100) { + if (decode_mb_count < mb_total) { + p->data_flag |= ERROR_FLAG; + if ((error_proc_policy & 0x20000) && + decode_mb_count >= mb_total * (100 - mb_count_threshold) / 100) { + p->data_flag &= ~ERROR_FLAG; + } + } + } + if (p->data_flag & ERROR_FLAG) { dpb_print(DECODE_ID(hw), PRINT_FLAG_ERRORFLAG_DBG, "%s: decode error, seq_info2 0x%x, mby_mbx 0x%x, mb_total %d decoded mb_count %d ERROR_STATUS_REG 0x%x\n", @@ -5432,6 +5606,157 @@ static void check_decoded_pic_error(struct vdec_h264_hw_s *hw) } } +static int vh264_pic_done_proc(struct vdec_s *vdec) +{ + struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)(vdec->private); + struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; + int ret; + + if (vdec->mvfrm) + vdec->mvfrm->hw_decode_time = + local_clock() - vdec->mvfrm->hw_decode_start; + + if (input_frame_based(vdec) && + (!(hw->i_only & 0x2)) && + frmbase_cont_bitlevel != 0 && + READ_VREG(VIFF_BIT_CNT) > + frmbase_cont_bitlevel) { + /*handle the case: multi pictures in one packet*/ + dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, + "%s H264_PIC_DATA_DONE decode slice count %d, continue (bitcnt 0x%x)\n", + __func__, + hw->decode_pic_count, + READ_VREG(VIFF_BIT_CNT)); + hw->frmbase_cont_flag = 1; + } else + hw->frmbase_cont_flag = 0; + + if (p_H264_Dpb->mVideo.dec_picture) { + get_picture_qos_info(p_H264_Dpb->mVideo.dec_picture); +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION + DEL_EXIST(hw, + p_H264_Dpb->mVideo.dec_picture) = 0; + if (vdec->master) { + struct vdec_h264_hw_s *hw_ba = + (struct vdec_h264_hw_s *) + vdec->master->private; + if (hw_ba->last_dec_picture) + DEL_EXIST(hw_ba, + hw_ba->last_dec_picture) + = 1; + } +#endif + mutex_lock(&hw->chunks_mutex); + if (hw->chunk) { + p_H264_Dpb->mVideo.dec_picture->pts = + hw->chunk->pts; + p_H264_Dpb->mVideo.dec_picture->pts64 = + hw->chunk->pts64; + p_H264_Dpb->mVideo.dec_picture->timestamp = + hw->chunk->timestamp; +#ifdef MH264_USERDATA_ENABLE + vmh264_udc_fill_vpts(hw, + p_H264_Dpb->mSlice.slice_type, + hw->chunk->pts, 1); +#endif + +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION + } else if (vdec->master) { + /*dv enhance layer, + do not checkout pts*/ + struct StorablePicture *pic = + p_H264_Dpb->mVideo.dec_picture; + pic->pts = 0; + pic->pts64 = 0; +#endif + } else { + struct StorablePicture *pic = + p_H264_Dpb->mVideo.dec_picture; + u32 offset = pic->offset_delimiter; + if (pts_pickout_offset_us64(PTS_TYPE_VIDEO, + offset, &pic->pts, 0, &pic->pts64)) { + pic->pts = 0; + pic->pts64 = 0; +#ifdef MH264_USERDATA_ENABLE + vmh264_udc_fill_vpts(hw, + p_H264_Dpb->mSlice.slice_type, + pic->pts, 0); +#endif + } else { +#ifdef MH264_USERDATA_ENABLE + vmh264_udc_fill_vpts(hw, + p_H264_Dpb->mSlice.slice_type, + pic->pts, 1); +#endif + } + + } + mutex_unlock(&hw->chunks_mutex); + + check_decoded_pic_error(hw); +#ifdef ERROR_HANDLE_TEST + if ((hw->data_flag & ERROR_FLAG) + && (error_proc_policy & 0x80)) { + release_cur_decoding_buf(hw); + h264_clear_dpb(hw); + hw->dec_flag = 0; + hw->data_flag = 0; + hw->skip_frame_count = 0; + hw->has_i_frame = 0; + hw->no_error_count = 0xfff; + hw->no_error_i_count = 0xf; + } else +#endif + ret = store_picture_in_dpb(p_H264_Dpb, + p_H264_Dpb->mVideo.dec_picture, + hw->data_flag | hw->dec_flag | + p_H264_Dpb->mVideo.dec_picture->data_flag); + + + + if (ret == -1) { + release_cur_decoding_buf(hw); + bufmgr_force_recover(p_H264_Dpb); + } else { + if (hw->data_flag & ERROR_FLAG) { + hw->no_error_count = 0; + hw->no_error_i_count = 0; + } else { + hw->no_error_count++; + if (hw->data_flag & I_FLAG) + hw->no_error_i_count++; + } + if (hw->mmu_enable) + hevc_set_unused_4k_buff_idx(hw, + p_H264_Dpb->mVideo. + dec_picture->buf_spec_num); + bufmgr_post(p_H264_Dpb); + hw->last_dec_picture = + p_H264_Dpb->mVideo.dec_picture; + p_H264_Dpb->mVideo.dec_picture = NULL; + /* dump_dpb(&p_H264_Dpb->mDPB); */ + hw->has_i_frame = 1; + if (hw->mmu_enable) + hevc_set_frame_done(hw); + hw->decode_pic_count++; + p_H264_Dpb->decode_pic_count = hw->decode_pic_count; + if (hw->skip_frame_count > 0) { + /*skip n frame after first I */ + hw->skip_frame_count--; + if (hw->skip_frame_count == 0) + hw->dec_flag &= (~NODISP_FLAG); + } else if (hw->skip_frame_count < -1) { + /*skip n frame after first I until second I */ + hw->skip_frame_count++; + if (hw->skip_frame_count == -1) + hw->dec_flag &= (~NODISP_FLAG); + } + } + } + return 0; +} + + static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq) { int i; @@ -5439,16 +5764,10 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq) struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; unsigned int dec_dpb_status = p_H264_Dpb->dec_dpb_status; u32 debug_tag; - int ret; if (dec_dpb_status == H264_CONFIG_REQUEST) { #if 1 unsigned short *p = (unsigned short *)hw->lmem_addr; - dma_sync_single_for_cpu( - amports_get_dma_device(), - hw->lmem_addr_remap, - PAGE_SIZE, - DMA_FROM_DEVICE); for (i = 0; i < (RPM_END-RPM_BEGIN); i += 4) { int ii; for (ii = 0; ii < 4; ii++) { @@ -5495,6 +5814,20 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq) reset_process_time(hw); hw->reg_iqidct_control = READ_VREG(IQIDCT_CONTROL); hw->dec_result = DEC_RESULT_CONFIG_PARAM; +#ifdef DETECT_WRONG_MULTI_SLICE + /*restart check count and set 'unknown'*/ + dpb_print(DECODE_ID(hw), PRINT_FLAG_UCODE_EVT, + "%s MULTI_SLICE_DETECT (check_count %d slice_count %d cur_slice_count %d flag %d), H264_CONFIG_REQUEST => restart check\n", + __func__, + hw->multi_slice_pic_check_count, + hw->picture_slice_count, + hw->cur_picture_slice_count, + hw->multi_slice_pic_flag); + + hw->multi_slice_pic_check_count = 0; + hw->multi_slice_pic_flag = 0; + hw->picture_slice_count = 0; +#endif vdec_schedule_work(&hw->work); } else if (dec_dpb_status == H264_SLICE_HEAD_DONE) { u16 data_hight; @@ -5503,21 +5836,42 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq) int slice_header_process_status = 0; int I_flag; + int frame_num_gap = 0; /*unsigned char is_idr;*/ unsigned short *p = (unsigned short *)hw->lmem_addr; reset_process_time(hw); - if (hw->is_used_v4l) { - struct aml_vcodec_ctx *ctx = - (struct aml_vcodec_ctx *)(hw->v4l2_ctx); - - if (ctx->param_sets_from_ucode && !ctx->v4l_codec_ready) { - //amvdec_stop(); - hw->dec_result = DEC_RESULT_DONE; - vdec_schedule_work(&hw->work); - return IRQ_HANDLED; +#ifdef DETECT_WRONG_MULTI_SLICE + hw->cur_picture_slice_count++; + if (hw->multi_slice_pic_flag == 1 && + hw->cur_picture_slice_count == 1 && + (error_proc_policy & 0x10000)) { + hw->first_pre_frame_num = p_H264_Dpb->mVideo.pre_frame_num; + } + if (hw->multi_slice_pic_flag == 1 && + hw->cur_picture_slice_count > 1 && + (error_proc_policy & 0x10000)) { + dpb_print(DECODE_ID(hw), 0, + "%s MULTI_SLICE_DETECT (check_count %d slice_count %d cur_slice_count %d flag %d), WRONG_MULTI_SLICE detected, insert picture\n", + __func__, + hw->multi_slice_pic_check_count, + hw->picture_slice_count, + hw->cur_picture_slice_count, + hw->multi_slice_pic_flag); + if (hw->cur_picture_slice_count > hw->last_picture_slice_count) + vh264_pic_done_proc(vdec); + else { + if (p_H264_Dpb->mVideo.dec_picture) { + if (p_H264_Dpb->mVideo.dec_picture->colocated_buf_index >= 0) { + release_colocate_buf(p_H264_Dpb, + p_H264_Dpb->mVideo.dec_picture->colocated_buf_index); + p_H264_Dpb->mVideo.dec_picture->colocated_buf_index = -1; + } + } + release_cur_decoding_buf(hw); } } +#endif hw->reg_iqidct_control = READ_VREG(IQIDCT_CONTROL); hw->reg_vcop_ctrl_reg = READ_VREG(VCOP_CTRL_REG); @@ -5536,11 +5890,6 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq) goto empty_proc; } - dma_sync_single_for_cpu( - amports_get_dma_device(), - hw->lmem_addr_remap, - PAGE_SIZE, - DMA_FROM_DEVICE); #if 0 if (p_H264_Dpb->mVideo.dec_picture == NULL) { if (!is_buffer_available(vdec)) { @@ -5687,7 +6036,7 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq) } slice_header_process_status = - h264_slice_header_process(p_H264_Dpb); + h264_slice_header_process(p_H264_Dpb, &frame_num_gap); if (hw->mmu_enable) hevc_sao_set_slice_type(hw, slice_header_process_status, @@ -5744,23 +6093,16 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq) READ_VREG(MBY_MBX), decode_mb_count); p->data_flag |= ERROR_FLAG; - } else if (!p_H264_Dpb->dpb_param.l.data[FIRST_MB_IN_SLICE] && decode_mb_count) { + }/* else if (!p_H264_Dpb->dpb_param.l.data[FIRST_MB_IN_SLICE] && decode_mb_count) { p->data_flag |= ERROR_FLAG; goto pic_done_proc; - } + }*/ } - if (p_H264_Dpb->mVideo.dec_picture->slice_type == I_SLICE) { - hw->new_iframe_flag = 1; - } - if (hw->new_iframe_flag) { - if (p_H264_Dpb->mVideo.dec_picture->slice_type == P_SLICE) { - hw->new_iframe_flag = 0; - hw->ref_err_flush_dpb_flag = 1; - }else if (p_H264_Dpb->mVideo.dec_picture->slice_type == B_SLICE) { - hw->new_iframe_flag = 0; - hw->ref_err_flush_dpb_flag = 0; - } + if (!I_flag && frame_num_gap) { + hw->data_flag |= ERROR_FLAG; + p_H264_Dpb->mVideo.dec_picture->data_flag |= ERROR_FLAG; + dpb_print(DECODE_ID(hw), 0, "frame number gap error\n"); } if (error_proc_policy & 0x400) { @@ -5774,15 +6116,6 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq) hw->skip_frame_count, hw->reflist_error_count); - if (hw->ref_err_flush_dpb_flag) { - flush_dpb(p_H264_Dpb); - p_H264_Dpb->colocated_buf_map = 0; - if (p_H264_Dpb->mVideo.dec_picture->colocated_buf_index >= 0) { - p_H264_Dpb->colocated_buf_map |= 1 << - p_H264_Dpb->mVideo.dec_picture->colocated_buf_index; - } - } - p_H264_Dpb->mVideo.dec_picture->data_flag = NODISP_FLAG; if (((error_proc_policy & 0x80) && ((hw->dec_flag & @@ -5844,146 +6177,37 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq) start_process_time(hw); } else if (dec_dpb_status == H264_PIC_DATA_DONE ||((dec_dpb_status == H264_DATA_REQUEST) && input_frame_based(vdec))) { -pic_done_proc: - reset_process_time(hw); - - if (input_frame_based(vdec) && - (!(hw->i_only & 0x2)) && - frmbase_cont_bitlevel != 0 && - READ_VREG(VIFF_BIT_CNT) > - frmbase_cont_bitlevel) { - /*handle the case: multi pictures in one packet*/ - dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, - "%s H264_PIC_DATA_DONE decode slice count %d, continue (bitcnt 0x%x)\n", - __func__, - hw->decode_pic_count, - READ_VREG(VIFF_BIT_CNT)); - hw->frmbase_cont_flag = 1; - } else - hw->frmbase_cont_flag = 0; - - if (p_H264_Dpb->mVideo.dec_picture) { - get_picture_qos_info(p_H264_Dpb->mVideo.dec_picture); -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - DEL_EXIST(hw, - p_H264_Dpb->mVideo.dec_picture) = 0; - if (vdec->master) { - struct vdec_h264_hw_s *hw_ba = - (struct vdec_h264_hw_s *) - vdec->master->private; - if (hw_ba->last_dec_picture) - DEL_EXIST(hw_ba, - hw_ba->last_dec_picture) - = 1; - } -#endif - mutex_lock(&hw->chunks_mutex); - if (hw->chunk) { - p_H264_Dpb->mVideo.dec_picture->pts = - hw->chunk->pts; - p_H264_Dpb->mVideo.dec_picture->pts64 = - hw->chunk->pts64; - p_H264_Dpb->mVideo.dec_picture->timestamp = - hw->chunk->timestamp; -#ifdef MH264_USERDATA_ENABLE - vmh264_udc_fill_vpts(hw, - p_H264_Dpb->mSlice.slice_type, - hw->chunk->pts, 1); -#endif - -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - } else if (vdec->master) { - /*dv enhance layer, - do not checkout pts*/ - struct StorablePicture *pic = - p_H264_Dpb->mVideo.dec_picture; - pic->pts = 0; - pic->pts64 = 0; -#endif - } else { - struct StorablePicture *pic = - p_H264_Dpb->mVideo.dec_picture; - u32 offset = pic->offset_delimiter; - if (pts_pickout_offset_us64(PTS_TYPE_VIDEO, - offset, &pic->pts, 0, &pic->pts64)) { - pic->pts = 0; - pic->pts64 = 0; -#ifdef MH264_USERDATA_ENABLE - vmh264_udc_fill_vpts(hw, - p_H264_Dpb->mSlice.slice_type, - pic->pts, 0); -#endif - } else { -#ifdef MH264_USERDATA_ENABLE - vmh264_udc_fill_vpts(hw, - p_H264_Dpb->mSlice.slice_type, - pic->pts, 1); -#endif +#ifdef DETECT_WRONG_MULTI_SLICE + dpb_print(DECODE_ID(hw), PRINT_FLAG_UCODE_EVT, + "%s MULTI_SLICE_DETECT (check_count %d slice_count %d cur_slice_count %d flag %d), H264_PIC_DATA_DONE\n", + __func__, + hw->multi_slice_pic_check_count, + hw->picture_slice_count, + hw->cur_picture_slice_count, + hw->multi_slice_pic_flag); + + if (hw->multi_slice_pic_check_count < check_slice_num) { + hw->multi_slice_pic_check_count++; + if (hw->cur_picture_slice_count != + hw->picture_slice_count) { + /*restart check count and set 'unknown'*/ + hw->multi_slice_pic_check_count = 0; + hw->multi_slice_pic_flag = 0; + } + hw->picture_slice_count = + hw->cur_picture_slice_count; + } else if (hw->multi_slice_pic_check_count >= check_slice_num) { + if (hw->picture_slice_count > 1) + hw->multi_slice_pic_flag = 2; + else + hw->multi_slice_pic_flag = 1; } - - } - mutex_unlock(&hw->chunks_mutex); - - check_decoded_pic_error(hw); -#ifdef ERROR_HANDLE_TEST - if ((hw->data_flag & ERROR_FLAG) - && (error_proc_policy & 0x80)) { - release_cur_decoding_buf(hw); - h264_clear_dpb(hw); - hw->dec_flag = 0; - hw->data_flag = 0; - hw->skip_frame_count = 0; - hw->has_i_frame = 0; - hw->no_error_count = 0xfff; - hw->no_error_i_count = 0xf; - } else #endif - ret = store_picture_in_dpb(p_H264_Dpb, - p_H264_Dpb->mVideo.dec_picture, - hw->data_flag | hw->dec_flag | - p_H264_Dpb->mVideo.dec_picture->data_flag); - +pic_done_proc: + reset_process_time(hw); + vh264_pic_done_proc(vdec); - if (ret == -1) { - release_cur_decoding_buf(hw); - bufmgr_force_recover(p_H264_Dpb); - } else { - if (hw->data_flag & ERROR_FLAG) { - hw->no_error_count = 0; - hw->no_error_i_count = 0; - } else { - hw->no_error_count++; - if (hw->data_flag & I_FLAG) - hw->no_error_i_count++; - } - if (hw->mmu_enable) - hevc_set_unused_4k_buff_idx(hw, - p_H264_Dpb->mVideo. - dec_picture->buf_spec_num); - bufmgr_post(p_H264_Dpb); - hw->last_dec_picture = - p_H264_Dpb->mVideo.dec_picture; - p_H264_Dpb->mVideo.dec_picture = NULL; - /* dump_dpb(&p_H264_Dpb->mDPB); */ - hw->has_i_frame = 1; - if (hw->mmu_enable) - hevc_set_frame_done(hw); - hw->decode_pic_count++; - p_H264_Dpb->decode_pic_count = hw->decode_pic_count; - if (hw->skip_frame_count > 0) { - /*skip n frame after first I */ - hw->skip_frame_count--; - if (hw->skip_frame_count == 0) - hw->dec_flag &= (~NODISP_FLAG); - } else if (hw->skip_frame_count < -1) { - /*skip n frame after first I until second I */ - hw->skip_frame_count++; - if (hw->skip_frame_count == -1) - hw->dec_flag &= (~NODISP_FLAG); - } - } - } if (hw->frmbase_cont_flag) { /*do not DEC_RESULT_GET_DATA*/ hw->get_data_count = 0x7fffffff; @@ -6034,11 +6258,6 @@ pic_done_proc: } else if (dec_dpb_status == H264_AUX_DATA_READY) { reset_process_time(hw); if (READ_VREG(H264_AUX_DATA_SIZE) != 0) { - dma_sync_single_for_cpu( - amports_get_dma_device(), - hw->aux_phy_addr, - hw->prefix_aux_size + hw->suffix_aux_size, - DMA_FROM_DEVICE); if (dpb_is_debug(DECODE_ID(hw), PRINT_FLAG_DPB_DETAIL)) dump_aux_buf(hw); @@ -6082,6 +6301,9 @@ pic_done_proc: (dec_dpb_status == H264_DECODE_TIMEOUT)) { empty_proc: reset_process_time(hw); + if ((error_proc_policy & 0x40000) && + dec_dpb_status == H264_DECODE_TIMEOUT) + goto pic_done_proc; if (!hw->frmbase_cont_flag) release_cur_decoding_buf(hw); @@ -6133,6 +6355,14 @@ empty_proc: vdec_schedule_work(&hw->work); } else { /* WRITE_VREG(DPB_STATUS_REG, H264_ACTION_INIT); */ +#ifdef DETECT_WRONG_MULTI_SLICE + if (hw->multi_slice_pic_flag == 1 && + hw->cur_picture_slice_count > 1 && + (error_proc_policy & 0x10000)) { + p_H264_Dpb->mVideo.pre_frame_num = hw->first_pre_frame_num; + } + hw->last_picture_slice_count = hw->cur_picture_slice_count; +#endif dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, "%s DEC_RESULT_AGAIN\n", __func__); send_again: @@ -6182,11 +6412,6 @@ send_again: u8 *sei_data_buf; u8 swap_byte; - dma_sync_single_for_cpu( - amports_get_dma_device(), - hw->aux_phy_addr, - hw->prefix_aux_size + hw->suffix_aux_size, - DMA_FROM_DEVICE); #if 0 dump_aux_buf(hw); #endif @@ -6240,12 +6465,6 @@ send_again: if (debug_tag & 0x10000) { unsigned short *p = (unsigned short *)hw->lmem_addr; - dma_sync_single_for_cpu( - amports_get_dma_device(), - hw->lmem_addr_remap, - PAGE_SIZE, - DMA_FROM_DEVICE); - dpb_print(DECODE_ID(hw), 0, "LMEM<tag %x>:\n", debug_tag); for (i = 0; i < 0x400; i += 4) { @@ -6317,9 +6536,11 @@ static irqreturn_t vh264_isr(struct vdec_s *vdec, int irq) p_H264_Dpb->dec_dpb_status = READ_VREG(DPB_STATUS_REG); dpb_print(DECODE_ID(hw), PRINT_FLAG_UCODE_EVT, - "%s DPB_STATUS_REG: 0x%x, ERROR_STATUS_REG 0x%x, sb (0x%x 0x%x 0x%x) bitcnt 0x%x mby_mbx 0x%x\n", + "%s DPB_STATUS_REG: 0x%x, run(%d) last_state (%x) ERROR_STATUS_REG 0x%x, sb (0x%x 0x%x 0x%x) bitcnt 0x%x mby_mbx 0x%x\n", __func__, p_H264_Dpb->dec_dpb_status, + run_count[DECODE_ID(hw)], + hw->dec_result, READ_VREG(ERROR_STATUS_REG), READ_VREG(VLD_MEM_VIFIFO_LEVEL), READ_VREG(VLD_MEM_VIFIFO_WP), @@ -6415,7 +6636,7 @@ static void vmh264_dump_state(struct vdec_s *vdec) ); dpb_print(DECODE_ID(hw), 0, - "is_framebase(%d), eos %d, state 0x%x, dec_result 0x%x dec_frm %d disp_frm %d run %d not_run_ready %d input_empty %d bufmgr_reset_cnt %d\n", + "is_framebase(%d), eos %d, state 0x%x, dec_result 0x%x dec_frm %d disp_frm %d run %d not_run_ready %d input_empty %d bufmgr_reset_cnt %d error_frame_count = %d, drop_frame_count = %d\n", input_frame_based(vdec), hw->eos, hw->stat, @@ -6425,9 +6646,21 @@ static void vmh264_dump_state(struct vdec_s *vdec) run_count[DECODE_ID(hw)], not_run_ready[DECODE_ID(hw)], input_empty[DECODE_ID(hw)], - hw->reset_bufmgr_count + hw->reset_bufmgr_count, + hw->gvs.error_frame_count, + hw->gvs.drop_frame_count ); +#ifdef DETECT_WRONG_MULTI_SLICE + dpb_print(DECODE_ID(hw), 0, + "MULTI_SLICE_DETECT (check_count %d slice_count %d cur_slice_count %d flag %d)\n", + hw->multi_slice_pic_check_count, + hw->picture_slice_count, + hw->cur_picture_slice_count, + hw->multi_slice_pic_flag); +#endif + + if (vf_get_receiver(vdec->vf_provider_name)) { enum receviver_start_e state = vf_notify_receiver(vdec->vf_provider_name, @@ -6561,7 +6794,8 @@ static void check_timer_func(unsigned long arg) return; } - if (vdec->next_status == VDEC_STATUS_DISCONNECTED) { + if (vdec->next_status == VDEC_STATUS_DISCONNECTED && + !hw->is_used_v4l) { hw->dec_result = DEC_RESULT_FORCE_EXIT; vdec_schedule_work(&hw->work); pr_debug("vdec requested to be disconnected\n"); @@ -6578,9 +6812,7 @@ static void check_timer_func(unsigned long arg) radr = 0; } - if ((input_frame_based(vdec) || - (READ_VREG(VLD_MEM_VIFIFO_LEVEL) > 0xb0)) && - ((h264_debug_flag & DISABLE_ERROR_HANDLE) == 0) && + if (((h264_debug_flag & DISABLE_ERROR_HANDLE) == 0) && (timeout_val > 0) && (hw->start_process_time > 0) && ((1000 * (jiffies - hw->start_process_time) / HZ) @@ -6629,7 +6861,7 @@ static void check_timer_func(unsigned long arg) static int dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) { - u32 ar; + u32 ar, ar_tmp; struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; if (!hw) @@ -6637,22 +6869,29 @@ static int dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) vstatus->frame_width = hw->frame_width; vstatus->frame_height = hw->frame_height; - if (hw->frame_dur != 0) + if (hw->frame_dur != 0) { + vstatus->frame_dur = hw->frame_dur; vstatus->frame_rate = 96000 / hw->frame_dur; + } else vstatus->frame_rate = -1; - vstatus->error_count = 0; + vstatus->error_count = hw->gvs.error_frame_count; vstatus->status = hw->stat; if (hw->h264_ar == 0x3ff) - hw->h264_ar = (0x100 * + ar_tmp = (0x100 * hw->frame_height * hw->height_aspect_ratio) / (hw->frame_width * hw->width_aspect_ratio); + else + ar_tmp = hw->h264_ar; ar = min_t(u32, - hw->h264_ar, + ar_tmp, DISP_RATIO_ASPECT_RATIO_MAX); vstatus->ratio_control = ar << DISP_RATIO_ASPECT_RATIO_BIT; + vstatus->error_frame_count = hw->gvs.error_frame_count; + vstatus->drop_frame_count = hw->gvs.drop_frame_count; + vstatus->frame_count = decode_frame_count[DECODE_ID(hw)]; snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name), "%s-%02d", DRIVER_NAME, hw->id); @@ -6731,6 +6970,8 @@ static int vh264_hw_ctx_restore(struct vdec_h264_hw_s *hw) && (v4l2_ctx->q_data[AML_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_NV21 || v4l2_ctx->q_data[AML_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_NV21M)) SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 16); + else + CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 16); SET_VREG_MASK(MDEC_PIC_DC_CTRL, 0xbf << 24); CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 0xbf << 24); @@ -6805,7 +7046,7 @@ static int vh264_hw_ctx_restore(struct vdec_h264_hw_s *hw) else*/ CLEAR_VREG_MASK(AV_SCRATCH_F, 1 << 6); - WRITE_VREG(LMEM_DUMP_ADR, (u32)hw->lmem_addr_remap); + WRITE_VREG(LMEM_DUMP_ADR, (u32)hw->lmem_phy_addr); #if 1 /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ WRITE_VREG(MDEC_PIC_DC_THRESH, 0x404038aa); #endif @@ -7057,28 +7298,15 @@ static s32 vh264_init(struct vdec_h264_hw_s *hw) } #if 1 /* #ifdef BUFFER_MGR_IN_C */ - hw->lmem_addr = __get_free_page(GFP_KERNEL); - if (!hw->lmem_addr) { - pr_info("%s: failed to alloc lmem_addr\n", __func__); - return -ENOMEM; - } else { - hw->lmem_addr_remap = dma_map_single( - amports_get_dma_device(), - (void *)hw->lmem_addr, - PAGE_SIZE, DMA_FROM_DEVICE); - if (dma_mapping_error(amports_get_dma_device(), - hw->lmem_addr_remap)) { - dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR, - "%s: failed to map lmem_addr\n", __func__); - free_page(hw->lmem_addr); - hw->lmem_addr = 0; - hw->lmem_addr_remap = 0; - return -ENOMEM; - } + hw->lmem_addr = (dma_addr_t)dma_alloc_coherent(amports_get_dma_device(), + PAGE_SIZE, (dma_addr_t *)&hw->lmem_phy_addr, GFP_KERNEL); - pr_debug("%s, vaddr=%lx phy_addr=%p\n", - __func__, hw->lmem_addr, (void *)hw->lmem_addr_remap); + if (hw->lmem_addr == 0) { + pr_err("%s: failed to alloc lmem buffer\n", __func__); + return -1; } + pr_debug("%s, phy_addr=%lx vaddr=%p\n", + __func__, hw->lmem_phy_addr, (void *)hw->lmem_addr); if (prefix_aux_buf_size > 0 || suffix_aux_buf_size > 0) { @@ -7086,21 +7314,14 @@ static s32 vh264_init(struct vdec_h264_hw_s *hw) hw->prefix_aux_size = AUX_BUF_ALIGN(prefix_aux_buf_size); hw->suffix_aux_size = AUX_BUF_ALIGN(suffix_aux_buf_size); aux_buf_size = hw->prefix_aux_size + hw->suffix_aux_size; - hw->aux_addr = kmalloc(aux_buf_size, GFP_KERNEL); + hw->aux_addr = dma_alloc_coherent(amports_get_dma_device(), + aux_buf_size, &hw->aux_phy_addr, + GFP_KERNEL); if (hw->aux_addr == NULL) { pr_err("%s: failed to alloc rpm buffer\n", __func__); return -1; } - hw->aux_phy_addr = dma_map_single(amports_get_dma_device(), - hw->aux_addr, aux_buf_size, DMA_FROM_DEVICE); - if (dma_mapping_error(amports_get_dma_device(), - hw->aux_phy_addr)) { - pr_err("%s: failed to map rpm buffer\n", __func__); - kfree(hw->aux_addr); - hw->aux_addr = NULL; - return -1; - } hw->sei_data_buf = kmalloc(SEI_DATA_SIZE, GFP_KERNEL); if (hw->sei_data_buf == NULL) { pr_err("%s: failed to alloc sei itu data buffer\n", @@ -7111,7 +7332,9 @@ static s32 vh264_init(struct vdec_h264_hw_s *hw) if (hw->sei_itu_data_buf == NULL) { pr_err("%s: failed to alloc sei itu data buffer\n", __func__); - kfree(hw->aux_addr); + dma_free_coherent(amports_get_dma_device(), + hw->prefix_aux_size + hw->suffix_aux_size, hw->aux_addr, + hw->aux_phy_addr); hw->aux_addr = NULL; kfree(hw->sei_data_buf); hw->sei_data_buf = NULL; @@ -7125,7 +7348,9 @@ static s32 vh264_init(struct vdec_h264_hw_s *hw) if (!hw->sei_user_data_buffer) { pr_info("%s: Can not allocate sei_data_buffer\n", __func__); - kfree(hw->aux_addr); + dma_free_coherent(amports_get_dma_device(), + hw->prefix_aux_size + hw->suffix_aux_size, hw->aux_addr, + hw->aux_phy_addr); hw->aux_addr = NULL; kfree(hw->sei_data_buf); hw->sei_data_buf = NULL; @@ -7183,22 +7408,17 @@ static int vh264_stop(struct vdec_h264_hw_s *hw) vdec_free_irq(VDEC_IRQ_1, (void *)hw); hw->stat &= ~STAT_ISR_REG; } - if (hw->lmem_addr_remap) { - dma_unmap_single(amports_get_dma_device(), - hw->lmem_addr_remap, - PAGE_SIZE, DMA_FROM_DEVICE); - hw->lmem_addr_remap = 0; - } if (hw->lmem_addr) { - free_page(hw->lmem_addr); + dma_free_coherent(amports_get_dma_device(), + PAGE_SIZE, (void *)hw->lmem_addr, + hw->lmem_phy_addr); hw->lmem_addr = 0; } + if (hw->aux_addr) { - dma_unmap_single(amports_get_dma_device(), - hw->aux_phy_addr, - hw->prefix_aux_size + hw->suffix_aux_size, - DMA_FROM_DEVICE); - kfree(hw->aux_addr); + dma_free_coherent(amports_get_dma_device(), + hw->prefix_aux_size + hw->suffix_aux_size, hw->aux_addr, + hw->aux_phy_addr); hw->aux_addr = NULL; } if (hw->sei_data_buf != NULL) { @@ -7884,6 +8104,117 @@ static void vmh264_wakeup_userdata_poll(struct vdec_s *vdec) #endif +static int vmh264_get_ps_info(struct vdec_h264_hw_s *hw, u32 param1, u32 param4, struct aml_vdec_ps_infos *ps) +{ + struct vdec_s *vdec = hw_to_vdec(hw); + int mb_width, mb_total; + int mb_height = 0; + int active_buffer_spec_num; + int max_reference_size ,level_idc; + unsigned int used_reorder_dpb_size_margin + = hw->reorder_dpb_size_margin; + int reorder_pic_num; + + level_idc = param4 & 0xff; + max_reference_size = (param4 >> 8) & 0xff; + +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION + if (vdec->master || vdec->slave) + used_reorder_dpb_size_margin = + reorder_dpb_size_margin_dv; +#endif + mb_width = param1 & 0xff; + mb_total = (param1 >> 8) & 0xffff; + if (!mb_width && mb_total) /*for 4k2k*/ + mb_width = 256; + if (mb_width) + mb_height = mb_total/mb_width; + if (mb_width <= 0 || mb_height <= 0 || + is_oversize(mb_width << 4, mb_height << 4)) { + dpb_print(DECODE_ID(hw), 0, + "!!!wrong param1 0x%x mb_width/mb_height (0x%x/0x%x) %x\r\n", + param1, + mb_width, + mb_height); + return -1; + } + + reorder_pic_num = + get_max_dec_frame_buf_size(level_idc, + max_reference_size, mb_width, mb_height); + + if ((hw->bitstream_restriction_flag) && + (hw->max_dec_frame_buffering < + reorder_pic_num)) { + reorder_pic_num = hw->max_dec_frame_buffering; + dpb_print(DECODE_ID(hw), 0, + "set reorder_pic_num to %d\n", + reorder_pic_num); + } + + active_buffer_spec_num = + reorder_pic_num + + used_reorder_dpb_size_margin; + + if (active_buffer_spec_num > MAX_VF_BUF_NUM) { + active_buffer_spec_num = MAX_VF_BUF_NUM; + reorder_pic_num = active_buffer_spec_num + - used_reorder_dpb_size_margin; + } + + if (hw->no_poc_reorder_flag) + reorder_pic_num = 1; + + ps->profile = level_idc; + ps->ref_frames = max_reference_size; + ps->mb_width = mb_width; + ps->mb_height = mb_height; + ps->visible_width = mb_width << 4; + ps->visible_height = mb_height << 4; + ps->coded_width = ALIGN(mb_width << 4, 64); + ps->coded_height = ALIGN(mb_height << 4, 64); + ps->reorder_frames = reorder_pic_num; + ps->dpb_size = active_buffer_spec_num; + + return 0; +} + +static int v4l_res_change(struct vdec_h264_hw_s *hw, u32 param1, u32 param4) +{ + struct aml_vcodec_ctx *ctx = + (struct aml_vcodec_ctx *)(hw->v4l2_ctx); + struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; + int ret = 0; + + if (ctx->param_sets_from_ucode && + hw->res_ch_flag == 0) { + if (param1 != 0 && + hw->seq_info2 != (param1 & (~0x80000000)) && + hw->seq_info2 != 0) /*picture size changed*/ { + struct aml_vdec_ps_infos ps; + dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, "h264 res_change\n"); + if (vmh264_get_ps_info(hw, param1, param4, &ps) < 0) { + dpb_print(DECODE_ID(hw), 0, "set parameters error\n"); + } + hw->v4l_params_parsed = false; + vdec_v4l_set_ps_infos(ctx, &ps); + vdec_v4l_res_ch_event(ctx); + hw->res_ch_flag = 1; + amvdec_stop(); + if (hw->mmu_enable) + amhevc_stop(); + hw->eos = 1; + flush_dpb(p_H264_Dpb); + //del_timer_sync(&hw->check_timer); + if (hw->is_used_v4l) + notify_v4l_eos(hw_to_vdec(hw)); + ret = 1; + } + } + + return ret; + +} static void vh264_work_implement(struct vdec_h264_hw_s *hw, struct vdec_s *vdec, int from) @@ -7909,34 +8240,48 @@ static void vh264_work_implement(struct vdec_h264_hw_s *hw, u32 param2 = READ_VREG(AV_SCRATCH_2); u32 param3 = READ_VREG(AV_SCRATCH_6); u32 param4 = READ_VREG(AV_SCRATCH_B); - - if (vh264_set_params(hw, param1, - param2, param3, param4) < 0) - dpb_print(DECODE_ID(hw), 0, "set parameters error\n"); - - WRITE_VREG(AV_SCRATCH_0, (hw->max_reference_size<<24) | - (hw->dpb.mDPB.size<<16) | - (hw->dpb.mDPB.size<<8)); - - if (hw->is_used_v4l) { - struct aml_vcodec_ctx *ctx = + struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)(hw->v4l2_ctx); - if (ctx->param_sets_from_ucode && !hw->v4l_params_parsed) { - struct aml_vdec_ps_infos ps; - - ps.visible_width = hw->frame_width; - ps.visible_height = hw->frame_height; - ps.coded_width = ALIGN(hw->frame_width, 64); - ps.coded_height = ALIGN(hw->frame_height, 64); - ps.dpb_size = hw->dpb.mDPB.size; - hw->v4l_params_parsed = true; - vdec_v4l_set_ps_infos(ctx, &ps); + if (hw->is_used_v4l && + ctx->param_sets_from_ucode) { + if (!v4l_res_change(hw, param1, param4)) { + if (!hw->v4l_params_parsed) { + struct aml_vdec_ps_infos ps; + dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, "h264 parsered csd data\n"); + if (vmh264_get_ps_info(hw, param1, param4, &ps) < 0) { + dpb_print(DECODE_ID(hw), 0, "set parameters error\n"); + } + hw->v4l_params_parsed = true; + vdec_v4l_set_ps_infos(ctx, &ps); + amvdec_stop(); + if (hw->mmu_enable) + amhevc_stop(); + } + else { + if (vh264_set_params(hw, param1, + param2, param3, param4) < 0) + dpb_print(DECODE_ID(hw), 0, "set parameters error\n"); + + WRITE_VREG(AV_SCRATCH_0, (hw->max_reference_size<<24) | + (hw->dpb.mDPB.size<<16) | + (hw->dpb.mDPB.size<<8)); + hw->res_ch_flag = 0; + start_process_time(hw); + return; + } } - } + } else { + if (vh264_set_params(hw, param1, + param2, param3, param4) < 0) + dpb_print(DECODE_ID(hw), 0, "set parameters error\n"); - start_process_time(hw); - return; + WRITE_VREG(AV_SCRATCH_0, (hw->max_reference_size<<24) | + (hw->dpb.mDPB.size<<16) | + (hw->dpb.mDPB.size<<8)); + start_process_time(hw); + return; + } } else if (((hw->dec_result == DEC_RESULT_GET_DATA) || (hw->dec_result == DEC_RESULT_GET_DATA_RETRY)) @@ -8043,6 +8388,22 @@ static void vh264_work_implement(struct vdec_h264_hw_s *hw, /* if (!hw->ctx_valid) hw->ctx_valid = 1; */ result_done: + { + if (error_proc_policy & 0x8000) { + struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; + int i; + struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB; + + for (i = 0; i < p_Dpb->used_size; i++) { + if (p_Dpb->fs[i]->dpb_frame_count + 500 < p_H264_Dpb->dpb_frame_count) { + dpb_print(DECODE_ID(hw), + 0, + "unmark reference dpb_frame_count diffrence large in dpb\n"); + unmark_for_reference(p_Dpb, p_Dpb->fs[i]); + } + } + } + } if (hw->mmu_enable && hw->frame_busy && hw->frame_done) { long used_4k_num; @@ -8127,7 +8488,10 @@ result_done: WRITE_VREG(ASSIST_MBOX1_MASK, 0); del_timer_sync(&hw->check_timer); hw->stat &= ~STAT_TIMER_ARM; - +#ifdef DETECT_WRONG_MULTI_SLICE + if (hw->dec_result != DEC_RESULT_AGAIN) + hw->last_picture_slice_count = 0; +#endif wait_vmh264_search_done(hw); /* mark itself has all HW resource released and input released */ @@ -8297,15 +8661,24 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)(hw->v4l2_ctx); - if (ctx->param_sets_from_ucode && - !ctx->v4l_codec_ready && - hw->v4l_params_parsed) { - ret = 0; /*the params has parsed.*/ + if (ctx->param_sets_from_ucode) { + if (hw->v4l_params_parsed) { + if (!ctx->v4l_codec_dpb_ready && + v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) < + run_ready_min_buf_num) + ret = 0; + } else { + if ((hw->res_ch_flag == 1) && + ((ctx->state <= AML_STATE_INIT) || + (ctx->state >= AML_STATE_FLUSHING))) + ret = 0; + } } else if (!ctx->v4l_codec_dpb_ready) { if (v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) < run_ready_min_buf_num) ret = 0; } + } if (ret) @@ -8358,6 +8731,10 @@ static void run(struct vdec_s *vdec, unsigned long mask, hw->vdec_cb_arg = arg; hw->vdec_cb = callback; +#ifdef DETECT_WRONG_MULTI_SLICE + hw->cur_picture_slice_count = 0; +#endif + if (kfifo_len(&hw->display_q) > VF_POOL_SIZE) { hw->reset_bufmgr_flag = 1; dpb_print(DECODE_ID(hw), 0, @@ -8504,7 +8881,7 @@ static void run(struct vdec_s *vdec, unsigned long mask, } vdec->mc_type = ((1 << 16) | VFORMAT_H264); } - vdec->mc_loaded = 1; + vdec->mc_loaded = 0; } vmh264_reset_udr_mgr(hw); @@ -8520,6 +8897,8 @@ static void run(struct vdec_s *vdec, unsigned long mask, WRITE_VREG(H264_DECODE_INFO, (1<<13)); WRITE_VREG(H264_DECODE_SIZE, decode_size); WRITE_VREG(VIFF_BIT_CNT, decode_size * 8); + if (vdec->mvfrm) + vdec->mvfrm->frame_size = hw->chunk->size; } else { if (size <= 0) size = 0x7fffffff; /*error happen*/ @@ -8553,6 +8932,8 @@ static void run(struct vdec_s *vdec, unsigned long mask, else CLEAR_VREG_MASK(VDEC_ASSIST_MMC_CTRL1, 1 << 3); } + if (vdec->mvfrm) + vdec->mvfrm->hw_decode_start = local_clock(); amvdec_start(); if (hw->mmu_enable /*&& !hw->frame_busy && !hw->frame_done*/) { WRITE_VREG(HEVC_ASSIST_SCRATCH_0, 0x0); @@ -8600,7 +8981,9 @@ static void reset(struct vdec_s *vdec) cancel_work_sync(&hw->work); cancel_work_sync(&hw->notify_work); if (hw->stat & STAT_VDEC_RUN) { - amhevc_stop(); + amvdec_stop(); + if (hw->mmu_enable) + amhevc_stop(); hw->stat &= ~STAT_VDEC_RUN; } @@ -8715,6 +9098,7 @@ static void h264_reset_bufmgr(struct vdec_s *vdec) { ulong timeout; struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; + struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; #if 0 struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; int actual_dpb_size, max_reference_size; @@ -8771,6 +9155,8 @@ static void h264_reset_bufmgr(struct vdec_s *vdec) __func__, hw->decode_pic_count+1, hw->skip_frame_count); + flush_dpb(&hw->dpb); + timeout = jiffies + HZ; while (kfifo_len(&hw->display_q) > 0) { if (time_after(jiffies, timeout)) @@ -8778,8 +9164,6 @@ static void h264_reset_bufmgr(struct vdec_s *vdec) schedule(); } - vf_notify_receiver(vdec->vf_provider_name, VFRAME_EVENT_PROVIDER_RESET, NULL); - buf_spec_init(hw); vh264_local_init(hw, true); @@ -8797,7 +9181,10 @@ static void h264_reset_bufmgr(struct vdec_s *vdec) if (first_i_policy & 0x01) hw->first_i_policy = (3 << 8) | first_i_policy; + p_H264_Dpb->first_insert_frame = FirstInsertFrm_RESET; + hw->init_flag = 1; + hw->reset_bufmgr_count++; #endif } @@ -8880,8 +9267,6 @@ static int ammvdec_h264_probe(struct platform_device *pdev) hw->mmu_enable = 0; hw->first_head_check_flag = 0; - hw->new_iframe_flag = 0; - hw->ref_err_flush_dpb_flag = 0; if (pdata->sys_info) hw->vh264_amstream_dec_info = *pdata->sys_info; @@ -9128,6 +9513,9 @@ static int ammvdec_h264_probe(struct platform_device *pdev) | CORE_MASK_COMBINE); atomic_set(&hw->vh264_active, 1); + vdec_set_vframe_comm(pdata, DRIVER_NAME); + display_frame_count[DECODE_ID(hw)] = 0; + decode_frame_count[DECODE_ID(hw)] = 0; return 0; } @@ -9483,6 +9871,11 @@ MODULE_PARM_DESC(mem_map_mode, "\n mem_map_mode\n"); module_param(without_display_mode, uint, 0664); MODULE_PARM_DESC(without_display_mode, "\n without_display_mode\n"); +module_param(check_slice_num, uint, 0664); +MODULE_PARM_DESC(check_slice_num, "\n check_slice_num\n"); + +module_param(mb_count_threshold, uint, 0664); +MODULE_PARM_DESC(mb_count_threshold, "\n mb_count_threshold\n"); module_init(ammvdec_h264_driver_init_module); module_exit(ammvdec_h264_driver_remove_module); |