summaryrefslogtreecommitdiff
authorYixin Peng <yixin.peng@amlogic.com>2019-11-27 13:29:00 (GMT)
committer Yixin Peng <yixin.peng@amlogic.com>2019-11-30 09:58:45 (GMT)
commit6cfc5cce37bcc8189a566285e01b32cfb3eaca37 (patch)
tree8c3541a6dac8410876e251f3e24ef287e08d7bb7
parentbfad586aed5b7001036404e1dd4c35efadf099e5 (diff)
downloadmedia_modules-6cfc5cce37bcc8189a566285e01b32cfb3eaca37.zip
media_modules-6cfc5cce37bcc8189a566285e01b32cfb3eaca37.tar.gz
media_modules-6cfc5cce37bcc8189a566285e01b32cfb3eaca37.tar.bz2
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 <yixin.peng@amlogic.com>
Diffstat
-rw-r--r--drivers/amvdec_ports/aml_vcodec_adapt.c8
-rw-r--r--drivers/amvdec_ports/aml_vcodec_adapt.h2
-rw-r--r--drivers/amvdec_ports/aml_vcodec_dec.c19
-rw-r--r--drivers/amvdec_ports/aml_vcodec_drv.h5
-rw-r--r--drivers/frame_provider/decoder/h264_multi/vmh264.c24
-rw-r--r--drivers/frame_provider/decoder/utils/vdec.c53
-rw-r--r--drivers/frame_provider/decoder/utils/vdec.h2
-rw-r--r--drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c3
8 files changed, 103 insertions, 13 deletions
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);