From: Nanxin Qin Date: Tue, 15 Sep 2020 13:16:01 +0000 (+0800) Subject: vmh264: add the feature of fence for h264 decoder. [2/2] X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=51c859b2765dea69354c706ca1da8971113d1b3c;p=GitHub%2FLineageOS%2FG12%2Fandroid_hardware_amlogic_kernel-modules_media.git vmh264: add the feature of fence for h264 decoder. [2/2] PD#SWPL-32845 Problem: need decode fence on cloud game docking Solution: 1. add the feature of fence for h264 decoder. 2. just used ip only stream source. Verify: u212 Change-Id: I80ed4f19d5f05c491e9599574cdb153c2a87b06d Signed-off-by: Nanxin Qin --- diff --git a/drivers/fake_video_out/fake_video.c b/drivers/fake_video_out/fake_video.c index c175c92..e0e9b16 100644 --- a/drivers/fake_video_out/fake_video.c +++ b/drivers/fake_video_out/fake_video.c @@ -37,12 +37,23 @@ #include #include "../frame_provider/decoder/utils/vdec.h" #include +#include #define RECEIVER_NAME "fake-amvideo" #define DEVICE_NAME "fake-amvideo" +#define TUNNEL_MODE (0) +#define NON_TUNNEL_MODE (1) + +static u32 display_mode = TUNNEL_MODE; +module_param(display_mode, uint, 0664); +MODULE_PARM_DESC(display_mode, "\n display_mode\n"); + static struct device *amvideo_dev = NULL; -struct work_struct worker; +struct timer_list timer; +struct task_struct *task; +bool thread_stop = false; +atomic_t frame_count; static struct vframe_receiver_s fake_video_vf_recv; static int video_receiver_event_fun(int type, void *data, void *); @@ -83,16 +94,20 @@ static int video_receiver_event_fun(int type, void *data, void *private_data) { switch (type) { case VFRAME_EVENT_PROVIDER_UNREG: { + atomic_set(&frame_count, 0); + pr_info("VFRAME_EVENT_PROVIDER_UNREG\n"); break; } case VFRAME_EVENT_PROVIDER_START: { + pr_info("VFRAME_EVENT_PROVIDER_START\n"); break; } case VFRAME_EVENT_PROVIDER_QUREY_STATE: { break; } case VFRAME_EVENT_PROVIDER_VFRAME_READY: { - vdec_schedule_work(&worker); + pr_info("VFRAME_EVENT_PROVIDER_VFRAME_READY\n"); + atomic_inc(&frame_count); break; } default: @@ -102,34 +117,72 @@ static int video_receiver_event_fun(int type, void *data, void *private_data) return 0; } -void displayer_worker(struct work_struct *work) +static void display_timer_func(unsigned long arg) { struct vframe_s *vf = NULL; - if (video_vf_peek()) { - vf = video_vf_get(); - if (!vf) { - pr_err("receiver vf err.\n"); - return; + if (display_mode != TUNNEL_MODE) + goto out; + + vf = video_vf_peek(); + if (!vf) { + goto out; + } + + if (vf->fence) { + if (vdec_fence_status_get(vf->fence) == 1) { + pr_info("[VDEC-FENCE]: Display, idx: %d\n", + vf->index & 0xff); + vf = video_vf_get(); + video_vf_put(vf); + } else { + pr_err("[VDEC-FENCE]: Display invalid, fence status err.\n"); } + } + +out: + mod_timer(&timer, jiffies + msecs_to_jiffies(16)); +} + +static int display_thread(void *data) +{ + struct vframe_s *vf = NULL; - /* add delay to simulation pipeline time*/ - udelay(2000); + for (;;) { + if (thread_stop) + break; - if (vf->fence) { - /* fence waiting until frame ready. */ - vdec_fence_wait(vf->fence, 2000); + if ((atomic_read(&frame_count) == 0) || + display_mode != NON_TUNNEL_MODE) + continue; - if (vdec_fence_status_get(vf->fence) == 1) { - pr_info("[VDEC-FENCE]: Display, idx: %d, dec cost: %lld\n", - vf->index & 0xff, local_clock() - get_sync_pt(vf->fence)->timestamp); - } else { - pr_err("[VDEC-FENCE]: Display invalid, fence status err.\n"); + if (video_vf_peek()) { + vf = video_vf_get(); + if (!vf) { + pr_err("receiver vf err.\n"); + break; } - } - video_vf_put(vf); + atomic_dec(&frame_count); + + if (vf->fence) { + u64 timestamp = local_clock(); + /* fence waiting until frame ready. */ + vdec_fence_wait(vf->fence, msecs_to_jiffies(2000)); + + if (vdec_fence_status_get(vf->fence) == 1) { + pr_info("[VDEC-FENCE]: Display, idx: %d, dec cost: %lld\n", + vf->index & 0xff, local_clock() - timestamp); + } else { + pr_err("[VDEC-FENCE]: Display invalid, fence status err.\n"); + } + } + + video_vf_put(vf); + } + msleep(16); } + return 0; } static int amvideo_open(struct inode *inode, struct file *file) @@ -173,7 +226,7 @@ static struct class amvideo_class = { .name = "fake_video", }; -#define FAKEVIDEO_MAJOR (21 + (AML_BASE)) +#define FAKEVIDEO_MAJOR (23 + (AML_BASE)) static int __init fake_video_init(void) { @@ -204,8 +257,21 @@ static int __init fake_video_init(void) &fake_video_vf_receiver, NULL); vf_reg_receiver(&fake_video_vf_recv); + atomic_set(&frame_count, 0); - INIT_WORK(&worker, displayer_worker); + init_timer(&timer); + //timer.data = 0; + timer.function = display_timer_func; + timer.expires = jiffies + HZ; + add_timer(&timer); + + thread_stop = false; + task = kthread_run(display_thread, NULL, "aml-%s", "fake-video-thread"); + if (IS_ERR(task)) { + ret = PTR_ERR(task); + pr_err("Failed to creat display thread, ret: %d.\n", ret); + goto err; + } return 0; @@ -219,7 +285,10 @@ err1: static void __exit fake_video_exit(void) { - cancel_work_sync(&worker); + thread_stop = true; + kthread_stop(task); + + del_timer_sync(&timer); vf_unreg_receiver(&fake_video_vf_recv); diff --git a/drivers/frame_provider/decoder/h264_multi/h264_dpb.c b/drivers/frame_provider/decoder/h264_multi/h264_dpb.c index 8ab6103..43d4719 100644 --- a/drivers/frame_provider/decoder/h264_multi/h264_dpb.c +++ b/drivers/frame_provider/decoder/h264_multi/h264_dpb.c @@ -1797,6 +1797,7 @@ void reset_frame_store(struct h264_dpb_stru *p_H264_Dpb, f->is_output = 0; f->pre_output = 0; + f->show_frame = false; f->frame = NULL; f->top_field = NULL; @@ -2160,6 +2161,7 @@ void bufmgr_h264_remove_unused_frame(struct h264_dpb_stru *p_H264_Dpb, struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB; int ret = 0; unsigned char removed_flag = 0; + do { ret = remove_unused_frame_from_dpb(p_H264_Dpb); if (ret != 0) @@ -2325,9 +2327,9 @@ int output_frames(struct h264_dpb_stru *p_H264_Dpb, unsigned char flush_flag) dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, "%s first_insert_frame %d \n", __func__, p_H264_Dpb->first_insert_frame); } - if (prepare_display_buf(p_H264_Dpb->vdec, p_Dpb->fs[pos]) >= 0) + if (prepare_display_buf(p_H264_Dpb->vdec, p_Dpb->fs[pos]) >= 0) { p_Dpb->fs[pos]->pre_output = 1; - else { + } else { if (h264_debug_flag & PRINT_FLAG_DPB_DETAIL) { dpb_print(p_H264_Dpb->decoder_index, 0, "%s[%d] poc:%d last_output_poc:%d poc_even_odd_flag:%d\n", @@ -5467,6 +5469,7 @@ void set_frame_output_flag(struct h264_dpb_stru *p_H264_Dpb, int index) p_H264_Dpb->mFrameStore[index].is_output = 1; p_H264_Dpb->mFrameStore[index].pre_output = 0; + p_H264_Dpb->mFrameStore[index].show_frame = false; dump_dpb(p_Dpb, 0); } @@ -5867,6 +5870,10 @@ int h264_slice_header_process(struct h264_dpb_stru *p_H264_Dpb, int *frame_num_g } } + if (post_picture_early(p_H264_Dpb->vdec, + p_H264_Dpb->mVideo.dec_picture->buf_spec_num)) + return -1; + if (p_H264_Dpb->mSlice.slice_type == P_SLICE) init_lists_p_slice(&p_H264_Dpb->mSlice); else if (p_H264_Dpb->mSlice.slice_type == B_SLICE) diff --git a/drivers/frame_provider/decoder/h264_multi/h264_dpb.h b/drivers/frame_provider/decoder/h264_multi/h264_dpb.h index ac549b0..0f7cb2d 100644 --- a/drivers/frame_provider/decoder/h264_multi/h264_dpb.h +++ b/drivers/frame_provider/decoder/h264_multi/h264_dpb.h @@ -819,9 +819,10 @@ struct FrameStore { int dpb_frame_count; u32 hw_decode_time; u32 frame_size2; // For recording the chunk->size in frame mode + bool show_frame; + struct fence *fence; }; - /* #define DPB_SIZE_MAX 16 */ #define DPB_SIZE_MAX 32 struct DecodedPictureBuffer { @@ -989,5 +990,6 @@ void unmark_for_reference(struct DecodedPictureBuffer *p_Dpb, void update_ref_list(struct DecodedPictureBuffer *p_Dpb); +int post_picture_early(struct vdec_s *vdec, int index); #endif diff --git a/drivers/frame_provider/decoder/h264_multi/vmh264.c b/drivers/frame_provider/decoder/h264_multi/vmh264.c index 2abf92e..d455516 100644 --- a/drivers/frame_provider/decoder/h264_multi/vmh264.c +++ b/drivers/frame_provider/decoder/h264_multi/vmh264.c @@ -345,7 +345,14 @@ static u32 without_display_mode; static u32 loop_playback_poc_threshold = 400; static u32 poc_threshold = 50; - +/* + *[3:0] 0: default use config from omx. + * 1: force enable fence. + * 2: disable fence. + *[7:4] 0: fence use for driver. + * 1: fence fd use for app. + */ +static u32 force_config_fence; #define IS_VDEC_DW(hw) (hw->double_write_mode >> 16 & 0xf) @@ -486,6 +493,7 @@ struct buffer_spec_s { /*unsigned int comp_body_size;*/ unsigned int dw_y_adr; unsigned int dw_u_v_adr; + int fs_idx; }; #define AUX_DATA_SIZE(pic) (hw->buffer_spec[pic->buf_spec_num].aux_data_size) @@ -909,6 +917,8 @@ struct vdec_h264_hw_s { int buffer_wrap[BUFSPEC_POOL_SIZE]; int loop_flag; int loop_last_poc; + bool enable_fence; + int fence_usage; }; static u32 again_threshold; @@ -2691,18 +2701,10 @@ static int is_iframe(struct FrameStore *frame) { return 0; } - - -int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) +static int post_prepare_process(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; if (buffer_index < 0 || buffer_index >= BUFSPEC_POOL_SIZE) { dpb_print(DECODE_ID(hw), 0, @@ -2711,13 +2713,6 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) 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 && @@ -2736,11 +2731,14 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) && (!(frame->data_flag & I_FLAG))) frame->data_flag |= ERROR_FLAG; } + dpb_print(DECODE_ID(hw), PRINT_FLAG_ERRORFLAG_DBG, - "%s, buffer_index 0x%x frame_error %x poc %d hw error %x error_proc_policy %x\n", - __func__, buffer_index, frame->data_flag & ERROR_FLAG, - frame->poc, hw->data_flag & ERROR_FLAG, - error_proc_policy); + "%s, buffer_index 0x%x frame_error %x poc %d hw error %x error_proc_policy %x\n", + __func__, buffer_index, + frame->data_flag & ERROR_FLAG, + frame->poc, hw->data_flag & ERROR_FLAG, + error_proc_policy); + if (frame->frame == NULL && ((frame->is_used == 1 && frame->top_field) || (frame->is_used == 2 && frame->bottom_field))) { @@ -2822,19 +2820,14 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) if ((frame->data_flag & NODISP_FLAG) || (frame->data_flag & NULL_FLAG) || ((!hw->send_error_frame_flag) && - (frame->data_flag & ERROR_FLAG)) || + (frame->data_flag & ERROR_FLAG)) || ((hw->i_only & 0x1) && - (!(frame->data_flag & I_FLAG))) - ) { + (!(frame->data_flag & I_FLAG)))) { set_frame_output_flag(&hw->dpb, frame->index); - return 0; /*do not return -1, - otherwise flush_dpb() will not flush all dbp frames*/ + frame->show_frame = false; } - display_frame_count[DECODE_ID(hw)]++; - - if (dpb_is_debug(DECODE_ID(hw), - PRINT_FLAG_DPB_DETAIL)) { + if (dpb_is_debug(DECODE_ID(hw), PRINT_FLAG_DPB_DETAIL)) { dpb_print(DECODE_ID(hw), 0, "%s, fs[%d] poc %d, buf_spec_num %d\n", __func__, frame->index, frame->poc, @@ -2847,16 +2840,41 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) frame->bottom_field, -1); } + frame->show_frame = true; + + return 0; +} + +static int post_video_frame(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 bForceInterlace = 0; + int vf_count = 1; + int i; + + /* 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 (!is_interlace(frame)) vf_count = 1; else vf_count = 2; + 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; + if (!hw->enable_fence) + hw->buffer_spec[buffer_index].vf_ref = 0; fill_frame_info(hw, frame); for (i = 0; i < vf_count; i++) { if (kfifo_get(&hw->newframe_q, &vf) == 0 || @@ -2884,6 +2902,12 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) = hw->buffer_spec[buffer_index].cma_alloc_addr; } + if (hw->enable_fence) { + /* fill fence information. */ + if (hw->fence_usage == FENCE_USE_FOR_DRIVER) + vf->fence = frame->fence; + } + if (hw->mmu_enable) { if (hw->double_write_mode & 0x10) { /* double write only */ @@ -2962,8 +2986,11 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) if (frame->data_flag & ERROR_FLAG) vf->flag |= VFRAME_FLAG_ERROR_RECOVERY; update_vf_memhandle(hw, vf, buffer_index); - hw->buffer_spec[buffer_index].used = 2; - hw->buffer_spec[buffer_index].vf_ref++; + + if (!hw->enable_fence) { + hw->buffer_spec[buffer_index].used = 2; + hw->buffer_spec[buffer_index].vf_ref++; + } dpb_print(DECODE_ID(hw), PRINT_FLAG_DPB_DETAIL, "%s %d frame = %p top_field = %p bottom_field = %p\n", __func__, __LINE__, frame->frame, @@ -3014,9 +3041,9 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) } dpb_print(DECODE_ID(hw), PRINT_FLAG_DPB_DETAIL, - "%s %d type = 0x%x pic_struct = %d pts = 0x%x pts_us64 = 0x%llx bForceInterlace = %d\n", - __func__, __LINE__, vf->type, frame->frame->pic_struct, - vf->pts, vf->pts_us64, bForceInterlace); + "%s %d type = 0x%x pic_struct = %d pts = 0x%x pts_us64 = 0x%llx bForceInterlace = %d\n", + __func__, __LINE__, vf->type, frame->frame->pic_struct, + vf->pts, vf->pts_us64, bForceInterlace); } if (i == 0) { struct vdec_s *pvdec; @@ -3057,6 +3084,76 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) return 0; } +int post_picture_early(struct vdec_s *vdec, int index) +{ + struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; + struct h264_dpb_stru *dpb_stru = &hw->dpb; + struct FrameStore fs; + u32 offset_lo, offset_hi; + + if (!hw->enable_fence) + return 0; + + /* create fence for each buffers. */ + if (vdec_timeline_create_fence(&vdec->sync)) + return -1; + + memset(&fs, 0, sizeof(fs)); + + fs.buf_spec_num = index; + fs.fence = vdec->sync.fence; + fs.slice_type = dpb_stru->mSlice.slice_type; + fs.dpb_frame_count = dpb_stru->dpb_frame_count; + + offset_lo = dpb_stru->dpb_param.l.data[OFFSET_DELIMITER_LO]; + offset_hi = dpb_stru->dpb_param.l.data[OFFSET_DELIMITER_HI]; + fs.offset_delimiter = (offset_lo | offset_hi << 16); + + if (hw->chunk) { + fs.pts = hw->chunk->pts; + fs.pts64 = hw->chunk->pts64; + fs.timestamp = hw->chunk->timestamp; + } + + post_video_frame(vdec, &fs); + + display_frame_count[DECODE_ID(hw)]++; + return 0; +} + +int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) +{ + struct vdec_h264_hw_s *hw = + (struct vdec_h264_hw_s *)vdec->private; + + if (hw->enable_fence) { + post_prepare_process(vdec, frame); + + if (!frame->show_frame) + pr_info("do not display.\n"); + + hw->buffer_spec[frame->buf_spec_num].used = 2; + hw->buffer_spec[frame->buf_spec_num].vf_ref = 1; + hw->buffer_spec[frame->buf_spec_num].fs_idx = frame->index; + + /* notify signal to wake up wq of fence. */ + vdec_timeline_increase(&vdec->sync, 1); + return 0; + } + + if (post_prepare_process(vdec, frame)) + return -1; + + if (!frame->show_frame) + return 0; + + if (post_video_frame(vdec, frame)) + return -1; + + display_frame_count[DECODE_ID(hw)]++; + return 0; +} + int notify_v4l_eos(struct vdec_s *vdec) { struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; @@ -4163,8 +4260,13 @@ static void vh264_vf_put(struct vframe_s *vf, void *op_arg) __func__, vf); return; } - frame_index = FRAME_INDEX(vf->index); + buf_spec_num = BUFSPEC_INDEX(vf->index); + if (hw->enable_fence) + frame_index = hw->buffer_spec[buf_spec_num].fs_idx; + else + frame_index = FRAME_INDEX(vf->index); + if (frame_index < 0 || frame_index >= DPB_SIZE_MAX || buf_spec_num < 0 || @@ -4176,6 +4278,12 @@ static void vh264_vf_put(struct vframe_s *vf, void *op_arg) } /*get_buf_spec_idx_by_canvas_config(hw, &vf->canvas0_config[0]);*/ + + if (hw->enable_fence && vf->fence) { + vdec_fence_put(vf->fence); + vf->fence = NULL; + } + spin_lock_irqsave(&hw->bufspec_lock, flags); if (hw->buffer_spec[buf_spec_num].used == 2) { struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; @@ -9780,9 +9888,32 @@ static int ammvdec_h264_probe(struct platform_device *pdev) if (get_config_int(pdata->config, "sidebind_channel_id", &config_val) == 0) hw->sidebind_channel_id = config_val; + + if (get_config_int(pdata->config, + "parm_enable_fence", + &config_val) == 0) + hw->enable_fence = config_val; + + if (get_config_int(pdata->config, + "parm_fence_usage", + &config_val) == 0) + hw->fence_usage = config_val; } else hw->double_write_mode = double_write_mode; + if (force_config_fence) { + hw->enable_fence = true; + hw->fence_usage = (force_config_fence >> 4) & 0xf; + if (force_config_fence & 0x2) + hw->enable_fence = false; + dpb_print(DECODE_ID(hw), 0, + "enable fence: %d, fence usage: %d\n", + hw->enable_fence, hw->fence_usage); + } + + if (hw->enable_fence) + pdata->sync.usage = hw->fence_usage; + if (!hw->is_used_v4l) { hw->reorder_dpb_size_margin = reorder_dpb_size_margin; hw->canvas_mode = mem_map_mode; @@ -9984,9 +10115,47 @@ static int ammvdec_h264_probe(struct platform_device *pdev) display_frame_count[DECODE_ID(hw)] = 0; decode_frame_count[DECODE_ID(hw)] = 0; + if (hw->enable_fence) { + /* creat timeline. */ + vdec_timeline_create(&pdata->sync, DRIVER_NAME); + } + return 0; } +static void vdec_fence_release(struct vdec_h264_hw_s *hw, + struct vdec_sync *sync) +{ + ulong expires; + int i; + + /* clear display pool. */ + clear_refer_bufs(hw); + + /* notify signal to wake up all fences. */ + vdec_timeline_increase(sync, VF_POOL_SIZE); + + expires = jiffies + msecs_to_jiffies(2000); + while (!check_objs_all_signaled(sync)) { + if (time_after(jiffies, expires)) { + pr_err("wait fence signaled timeout.\n"); + break; + } + } + + for (i = 0; i < VF_POOL_SIZE; i++) { + struct vframe_s *vf = &hw->vfpool[hw->cur_pool][i]; + + if (vf->fence) { + vdec_fence_put(vf->fence); + vf->fence = NULL; + } + } + + /* decreases refcnt of timeline. */ + vdec_timeline_put(sync); +} + static int ammvdec_h264_remove(struct platform_device *pdev) { struct vdec_h264_hw_s *hw = @@ -10050,6 +10219,9 @@ static int ammvdec_h264_remove(struct platform_device *pdev) } } + if (hw->enable_fence) + vdec_fence_release(hw, &vdec->sync); + ammvdec_h264_mmu_release(hw); h264_free_hw_stru(&pdev->dev, (void *)hw); clk_adj_frame_count = 0; @@ -10131,9 +10303,9 @@ static int __init ammvdec_h264_driver_init_module(void) if (vdec_is_support_4k()) { if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_TXLX) { ammvdec_h264_profile.profile = - "4k, dwrite, compressed, frame_dv"; + "4k, dwrite, compressed, frame_dv, fence"; } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXTVBB) { - ammvdec_h264_profile.profile = "4k, frame_dv"; + ammvdec_h264_profile.profile = "4k, frame_dv, fence"; } } @@ -10350,6 +10522,8 @@ MODULE_PARM_DESC(loop_playback_poc_threshold, "\n loop_playback_poc_threshold\n" module_param(poc_threshold, uint, 0664); MODULE_PARM_DESC(poc_threshold, "\n poc_threshold\n"); +module_param(force_config_fence, uint, 0664); +MODULE_PARM_DESC(force_config_fence, "\n force enable fence\n"); module_init(ammvdec_h264_driver_init_module); module_exit(ammvdec_h264_driver_remove_module); diff --git a/drivers/frame_provider/decoder/utils/vdec.c b/drivers/frame_provider/decoder/utils/vdec.c index f938f62..82180eb 100644 --- a/drivers/frame_provider/decoder/utils/vdec.c +++ b/drivers/frame_provider/decoder/utils/vdec.c @@ -2514,6 +2514,13 @@ s32 vdec_init(struct vdec_s *vdec, int is_4k) "amvideo"); snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE, "vdec-map-%d", vdec->id); + } else if (p->frame_base_video_path == + FRAME_BASE_PATH_AMLVIDEO_FENCE) { + snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE, + "%s %s", vdec->vf_provider_name, + "amlvideo amvideo"); + snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE, + "vdec-map-%d", vdec->id); } if (vfm_map_add(vdec->vfm_map_id, @@ -3432,7 +3439,6 @@ void vdec_power_reset(void) } EXPORT_SYMBOL(vdec_power_reset); - void vdec_poweron(enum vdec_type_e core) { if (core >= VDEC_MAX) diff --git a/drivers/frame_provider/decoder/utils/vdec_sync.c b/drivers/frame_provider/decoder/utils/vdec_sync.c index 855b822..01d7735 100644 --- a/drivers/frame_provider/decoder/utils/vdec_sync.c +++ b/drivers/frame_provider/decoder/utils/vdec_sync.c @@ -53,6 +53,7 @@ static struct sync_timeline *sync_timeline_create(const char *name) kref_init(&obj->kref); obj->context = fence_context_alloc(1); + obj->timestamp = local_clock(); strlcpy(obj->name, name, sizeof(obj->name)); INIT_LIST_HEAD(&obj->active_list_head); INIT_LIST_HEAD(&obj->pt_list); @@ -67,7 +68,6 @@ static void sync_timeline_free(struct kref *kref) container_of(kref, struct sync_timeline, kref); pr_info("[VDEC-FENCE] free timeline: %lx\n", (ulong) obj); - kfree(obj); } @@ -188,7 +188,7 @@ static void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc) obj->value += inc; list_for_each_entry_safe(pt, next, &obj->active_list_head, active_list) { - if (fence_is_signaled_locked(&pt->fence)) + if (fence_is_signaled(&pt->fence)) list_del_init(&pt->active_list); } spin_unlock_irqrestore(&obj->lock, flags); @@ -297,8 +297,8 @@ EXPORT_SYMBOL(vdec_fence_get); void vdec_fence_put(struct fence *fence) { if (debug & VDEC_DBG_ENABLE_FENCE) - pr_info("[VDEC-FENCE]: the fence cost time: %lld ns\n", - local_clock() - get_sync_pt(fence)->timestamp); + pr_info("[VDEC-FENCE]: the fence (%px) cost time: %lld ns\n", + fence, local_clock() - get_sync_pt(fence)->timestamp); fence_put(fence); } EXPORT_SYMBOL(vdec_fence_put); @@ -328,13 +328,26 @@ EXPORT_SYMBOL(vdec_timeline_create); int vdec_timeline_create_fence(struct vdec_sync *sync) { struct sync_timeline *obj = sync->timeline; + struct sync_pt *pt = NULL; + ulong flags; u32 value = 0; if (obj == NULL) return -EPERM; + spin_lock_irqsave(&obj->lock, flags); + + pt = list_last_entry(&obj->pt_list, struct sync_pt, link); value = obj->value + 1; + if (!list_empty(&obj->pt_list)) { + pt = list_last_entry(&obj->pt_list, struct sync_pt, link); + if (value == pt->fence.seqno) { + value++; + } + } + spin_unlock_irqrestore(&obj->lock, flags); + return timeline_create_fence(sync, sync->usage, &sync->fence, @@ -394,3 +407,21 @@ bool check_objs_all_signaled(struct vdec_sync *sync) } EXPORT_SYMBOL(check_objs_all_signaled); +int vdec_clean_all_fence(struct vdec_sync *sync) +{ + struct sync_timeline *obj = sync->timeline; + struct sync_pt *pt, *next; + + spin_lock_irq(&obj->lock); + + list_for_each_entry_safe(pt, next, &obj->pt_list, link) { + fence_set_error(&pt->fence, -ENOENT); + fence_signal_locked(&pt->fence); + } + + spin_unlock_irq(&obj->lock); + + return 0; +} +EXPORT_SYMBOL(vdec_clean_all_fence); + diff --git a/drivers/frame_provider/decoder/utils/vdec_sync.h b/drivers/frame_provider/decoder/utils/vdec_sync.h index fa07721..0622341 100644 --- a/drivers/frame_provider/decoder/utils/vdec_sync.h +++ b/drivers/frame_provider/decoder/utils/vdec_sync.h @@ -87,3 +87,5 @@ void vdec_fence_status_set(struct fence *fence, int status); bool check_objs_all_signaled(struct vdec_sync *sync); +int vdec_clean_all_fence(struct vdec_sync *sync); + diff --git a/drivers/frame_provider/decoder/vp9/vvp9.c b/drivers/frame_provider/decoder/vp9/vvp9.c index 5717d60..d6ac49a 100644 --- a/drivers/frame_provider/decoder/vp9/vvp9.c +++ b/drivers/frame_provider/decoder/vp9/vvp9.c @@ -11175,24 +11175,24 @@ static int __init amvdec_vp9_driver_init_module(void) if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { amvdec_vp9_profile.profile = - "8k, 10bit, dwrite, compressed"; + "8k, 10bit, dwrite, compressed, fence"; } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXL /*&& get_cpu_major_id() != MESON_CPU_MAJOR_ID_GXLX*/ && get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_TXL) { if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_TXLX) { if (vdec_is_support_4k()) amvdec_vp9_profile.profile = - "4k, 10bit, dwrite, compressed"; + "4k, 10bit, dwrite, compressed, fence"; else amvdec_vp9_profile.profile = - "10bit, dwrite, compressed"; + "10bit, dwrite, compressed, fence"; } else { if (vdec_is_support_4k()) amvdec_vp9_profile.profile = - "4k, 10bit, dwrite, compressed"; + "4k, 10bit, dwrite, compressed, fence"; else amvdec_vp9_profile.profile = - "10bit, dwrite, compressed"; + "10bit, dwrite, compressed, fence"; } } else {