From 6cfc5cce37bcc8189a566285e01b32cfb3eaca37 Mon Sep 17 00:00:00 2001 From: Yixin Peng Date: Wed, 27 Nov 2019 13:29:00 +0000 Subject: media_module: h264 add REQUEST_RESET message to user space [1/1] PD#SWPL-5313 Problem: When the decode driver needs to reset, a message needs to be sent to the user space for this operation. Solution: Add this feature. Verify: U212 Change-Id: If112862058db61b870dce0e0eb9d6d13c6109152 Signed-off-by: Yixin Peng --- diff --git a/drivers/amvdec_ports/aml_vcodec_adapt.c b/drivers/amvdec_ports/aml_vcodec_adapt.c index 7ac9ad5..367da7a 100644 --- a/drivers/amvdec_ports/aml_vcodec_adapt.c +++ b/drivers/amvdec_ports/aml_vcodec_adapt.c @@ -709,14 +709,16 @@ void aml_decoder_flush(struct aml_vdec_adapt *ada_ctx) vdec_set_eos(vdec, true); } -int aml_codec_reset(struct aml_vdec_adapt *ada_ctx) +int aml_codec_reset(struct aml_vdec_adapt *ada_ctx, int *flag) { struct vdec_s *vdec = ada_ctx->vdec; int ret = 0; if (vdec) { - vdec_set_eos(vdec, false); - ret = vdec_reset(vdec); + if (*flag != 2) + vdec_set_eos(vdec, false); + ret = vdec_v4l2_reset(vdec, *flag); + *flag = 0; } return ret; diff --git a/drivers/amvdec_ports/aml_vcodec_adapt.h b/drivers/amvdec_ports/aml_vcodec_adapt.h index b591699..dad2fe4 100644 --- a/drivers/amvdec_ports/aml_vcodec_adapt.h +++ b/drivers/amvdec_ports/aml_vcodec_adapt.h @@ -58,7 +58,7 @@ int is_need_to_buf(struct aml_vdec_adapt *ada_ctx); void aml_decoder_flush(struct aml_vdec_adapt *ada_ctx); -int aml_codec_reset(struct aml_vdec_adapt *ada_ctx); +int aml_codec_reset(struct aml_vdec_adapt *ada_ctx, int *flag); extern void dump_write(const char __user *buf, size_t count); diff --git a/drivers/amvdec_ports/aml_vcodec_dec.c b/drivers/amvdec_ports/aml_vcodec_dec.c index f0a0d88..4f256b5 100644 --- a/drivers/amvdec_ports/aml_vcodec_dec.c +++ b/drivers/amvdec_ports/aml_vcodec_dec.c @@ -207,6 +207,13 @@ void aml_vdec_dispatch_event(struct aml_vcodec_ctx *ctx, u32 changes) { struct v4l2_event event = {0}; + if (ctx->receive_cmd_stop) { + ctx->state = AML_STATE_ABORT; + changes = V4L2_EVENT_REQUEST_EXIT; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ABORT)", + ctx->id, __func__); + } + switch (changes) { case V4L2_EVENT_SRC_CH_RESOLUTION: case V4L2_EVENT_SRC_CH_HDRINFO: @@ -781,7 +788,7 @@ static void aml_vdec_reset(struct aml_vcodec_ctx *ctx) goto out; } - if (aml_codec_reset(ctx->ada_ctx)) { + if (aml_codec_reset(ctx->ada_ctx, &ctx->reset_flag)) { ctx->state = AML_STATE_ABORT; aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ABORT)", ctx->id, __func__); @@ -801,6 +808,7 @@ static void aml_vdec_reset(struct aml_vcodec_ctx *ctx) ctx->q_data[AML_Q_DATA_SRC].resolution_changed = false; v4l2_m2m_job_resume(ctx->dev->m2m_dev_dec, ctx->m2m_ctx); } + out: complete(&ctx->comp); return; @@ -982,7 +990,7 @@ static int vidioc_decoder_cmd(struct file *file, void *priv, /* flush src */ v4l2_m2m_buf_queue(ctx->m2m_ctx, &ctx->empty_flush_buf->vb); v4l2_m2m_try_schedule(ctx->m2m_ctx);//pay attention - + ctx->receive_cmd_stop = true; break; case V4L2_DEC_CMD_START: @@ -1008,9 +1016,10 @@ static int vidioc_decoder_streamon(struct file *file, void *priv, if (!V4L2_TYPE_IS_OUTPUT(q->type)) { if (ctx->is_stream_off) { mutex_lock(&ctx->state_lock); - if (ctx->state == AML_STATE_ACTIVE || + if ((ctx->state == AML_STATE_ACTIVE || ctx->state == AML_STATE_FLUSHING || - ctx->state == AML_STATE_FLUSHED) { + ctx->state == AML_STATE_FLUSHED) || + (ctx->reset_flag == 2)) { ctx->state = AML_STATE_RESET; ctx->v4l_codec_ready = false; ctx->v4l_codec_dpb_ready = false; @@ -1965,7 +1974,7 @@ void vdec_device_vf_run(struct aml_vcodec_ctx *ctx) { aml_v4l2_debug(3, "[%d] %s() [%d]", ctx->id, __func__, __LINE__); - if (ctx->state < AML_STATE_ACTIVE || + if (ctx->state < AML_STATE_INIT || ctx->state > AML_STATE_FLUSHED) return; diff --git a/drivers/amvdec_ports/aml_vcodec_drv.h b/drivers/amvdec_ports/aml_vcodec_drv.h index fb1930e..23cf08d 100644 --- a/drivers/amvdec_ports/aml_vcodec_drv.h +++ b/drivers/amvdec_ports/aml_vcodec_drv.h @@ -58,6 +58,8 @@ #define V4L2_EVENT_REQUEST_RESET (1 << 8) #define V4L2_EVENT_REQUEST_EXIT (1 << 9) + + /** * enum aml_hw_reg_idx - AML hw register base index */ @@ -157,6 +159,7 @@ enum aml_q_type { AML_Q_DATA_DST = 1, }; + /** * struct aml_q_data - Structure used to store information about queue */ @@ -439,6 +442,8 @@ struct aml_vcodec_ctx { spinlock_t slock; struct v4l2_config_parm config; bool is_stream_off; + int reset_flag; + int stop_cmd; }; /** diff --git a/drivers/frame_provider/decoder/h264_multi/vmh264.c b/drivers/frame_provider/decoder/h264_multi/vmh264.c index 38321bb..ddae0c4 100644 --- a/drivers/frame_provider/decoder/h264_multi/vmh264.c +++ b/drivers/frame_provider/decoder/h264_multi/vmh264.c @@ -847,6 +847,7 @@ struct vdec_h264_hw_s { bool ref_err_flush_dpb_flag; unsigned int first_i_policy; u32 reorder_dpb_size_margin; + bool wait_reset_done_flag; }; static u32 again_threshold; @@ -6349,7 +6350,7 @@ static void vmh264_dump_state(struct vdec_s *vdec) } dpb_print(DECODE_ID(hw), 0, - "%s, newq(%d/%d), dispq(%d/%d) vf prepare/get/put (%d/%d/%d), free_spec(%d), initdon(%d), used_size(%d/%d), unused_fr_dpb(%d) fast_output_enable %x\n", + "%s, newq(%d/%d), dispq(%d/%d) vf prepare/get/put (%d/%d/%d), free_spec(%d), initdon(%d), used_size(%d/%d), unused_fr_dpb(%d) fast_output_enable %x wait_reset_done_flag %d\n", __func__, kfifo_len(&hw->newframe_q), VF_POOL_SIZE, @@ -6362,7 +6363,8 @@ static void vmh264_dump_state(struct vdec_s *vdec) p_H264_Dpb->mDPB.init_done, p_H264_Dpb->mDPB.used_size, p_H264_Dpb->mDPB.size, is_there_unused_frame_from_dpb(&p_H264_Dpb->mDPB), - p_H264_Dpb->fast_output_enable + p_H264_Dpb->fast_output_enable, + hw->wait_reset_done_flag ); dump_dpb(&p_H264_Dpb->mDPB, 1); @@ -8213,6 +8215,8 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) ret = 0; /*the params has parsed.*/ } else if (!ctx->v4l_codec_dpb_ready) ret = 0; + else if (hw->wait_reset_done_flag) + ret = 0; } if (ret) @@ -8279,7 +8283,19 @@ static void run(struct vdec_s *vdec, unsigned long mask, if (hw->reset_bufmgr_flag || ((error_proc_policy & 0x40) && p_H264_Dpb->buf_alloc_fail)) { - h264_reset_bufmgr(vdec); + if (!hw->is_used_v4l) + h264_reset_bufmgr(vdec); + else { + struct aml_vcodec_ctx *ctx = + (struct aml_vcodec_ctx *)(hw->v4l2_ctx); + pr_info("v4l2 buffer reset\n"); + hw->wait_reset_done_flag = 1; + hw->reset_bufmgr_flag = 0; + vdec_v4l_post_evet(ctx, V4L2_EVENT_REQUEST_RESET); + hw->dec_result = DEC_RESULT_NONE; + vdec_schedule_work(&hw->work); + return; + } hw->reset_bufmgr_flag = 0; } @@ -8501,6 +8517,7 @@ static void reset(struct vdec_s *vdec) hw->dec_result = DEC_RESULT_NONE; reset_process_time(hw); h264_reset_bufmgr(vdec); + hw->wait_reset_done_flag = 0; dpb_print(DECODE_ID(hw), 0, "%s\n", __func__); } @@ -8793,6 +8810,7 @@ static int ammvdec_h264_probe(struct platform_device *pdev) hw->first_head_check_flag = 0; hw->new_iframe_flag = 0; hw->ref_err_flush_dpb_flag = 0; + hw->wait_reset_done_flag = 0; if (pdata->sys_info) hw->vh264_amstream_dec_info = *pdata->sys_info; diff --git a/drivers/frame_provider/decoder/utils/vdec.c b/drivers/frame_provider/decoder/utils/vdec.c index 1a6f982..5c9e1d5 100644 --- a/drivers/frame_provider/decoder/utils/vdec.c +++ b/drivers/frame_provider/decoder/utils/vdec.c @@ -1564,6 +1564,7 @@ EXPORT_SYMBOL(vdec_set_flag); void vdec_set_eos(struct vdec_s *vdec, bool eos) { struct vdec_core_s *core = vdec_core; + vdec->input.eos = eos; if (vdec->slave) @@ -2465,6 +2466,57 @@ int vdec_reset(struct vdec_s *vdec) } EXPORT_SYMBOL(vdec_reset); +int vdec_v4l2_reset(struct vdec_s *vdec, int flag) +{ + //trace_vdec_reset(vdec); /*DEBUG_TMP*/ + pr_debug("vdec_v4l2_reset %d\n", flag); + vdec_disconnect(vdec); + if (flag != 2) { + if (vdec->vframe_provider.name) + vf_unreg_provider(&vdec->vframe_provider); + + if ((vdec->slave) && (vdec->slave->vframe_provider.name)) + vf_unreg_provider(&vdec->slave->vframe_provider); + + if (vdec->reset) { + vdec->reset(vdec); + if (vdec->slave) + vdec->slave->reset(vdec->slave); + } + vdec->mc_loaded = 0;/*clear for reload firmware*/ + + vdec_input_release(&vdec->input); + + vdec_input_init(&vdec->input, vdec); + + vdec_input_prepare_bufs(&vdec->input, vdec->sys_info->width, + vdec->sys_info->height); + + vf_reg_provider(&vdec->vframe_provider); + vf_notify_receiver(vdec->vf_provider_name, + VFRAME_EVENT_PROVIDER_START, vdec); + + if (vdec->slave) { + vf_reg_provider(&vdec->slave->vframe_provider); + vf_notify_receiver(vdec->slave->vf_provider_name, + VFRAME_EVENT_PROVIDER_START, vdec->slave); + vdec->slave->mc_loaded = 0;/*clear for reload firmware*/ + } + } else { + if (vdec->reset) { + vdec->reset(vdec); + if (vdec->slave) + vdec->slave->reset(vdec->slave); + } + } + + vdec_connect(vdec); + + return 0; +} +EXPORT_SYMBOL(vdec_v4l2_reset); + + void vdec_free_cmabuf(void) { mutex_lock(&vdec_mutex); @@ -2693,6 +2745,7 @@ unsigned long vdec_ready_to_run(struct vdec_s *vdec, unsigned long mask) inc_profi_count(mask, vdec->check_count); #endif if (vdec_core_with_input(mask)) { + /* check frame based input underrun */ if (input && !input->eos && input_frame_based(input) && (!vdec_input_next_chunk(input))) { diff --git a/drivers/frame_provider/decoder/utils/vdec.h b/drivers/frame_provider/decoder/utils/vdec.h index 80fa8dc..59ee2db 100644 --- a/drivers/frame_provider/decoder/utils/vdec.h +++ b/drivers/frame_provider/decoder/utils/vdec.h @@ -360,6 +360,8 @@ extern int vdec_destroy(struct vdec_s *vdec); /* reset vdec */ extern int vdec_reset(struct vdec_s *vdec); +extern int vdec_v4l2_reset(struct vdec_s *vdec, int flag); + extern void vdec_set_status(struct vdec_s *vdec, int status); extern void vdec_set_next_status(struct vdec_s *vdec, int status); diff --git a/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c b/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c index 19be624..107efec 100644 --- a/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c +++ b/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c @@ -51,7 +51,8 @@ int vdec_v4l_post_evet(struct aml_vcodec_ctx *ctx, u32 event) if (ctx->drv_handle == 0) return -EIO; - + if (event == 1) + ctx->reset_flag = 2; ret = ctx->dec_if->set_param(ctx->drv_handle, SET_PARAM_POST_EVENT, &event); -- cgit