summaryrefslogtreecommitdiff
authorshihong.zheng <shihong.zheng@amlogic.com>2020-03-19 05:11:57 (GMT)
committer Shen Liu <shen.liu@amlogic.com>2020-03-24 10:59:02 (GMT)
commit8cc771eb8b9b67f9cc4999e119d3148c8136bdf3 (patch)
tree87792c4a982055ad322208d74fd4d40b50be515a
parent64e9372b25ce5e713672bf478b6078fca08781a0 (diff)
downloadmedia_modules-8cc771eb8b9b67f9cc4999e119d3148c8136bdf3.zip
media_modules-8cc771eb8b9b67f9cc4999e119d3148c8136bdf3.tar.gz
media_modules-8cc771eb8b9b67f9cc4999e119d3148c8136bdf3.tar.bz2
mpeg12: update mpeg12 multi instance code. [1/1]
PD#SWPL-22463 Problem: mpeg12 video play failed. timeout repeatly and crash reboot. Solution: 1. optmized mpeg2 multi instance code. 2. fix first frame two times output and last frame do not flush output; 3. do not config and alloc bmmu buf repeatly; 4. set error skip 2, no mosaic output; 5. fix resolution switch error; 6. reduce timeout trig time in amvdec. avoid softirq long error. Verify: u212 Change-Id: Ided6392f429392f1af0abf66d4026e70d49c0c4d Signed-off-by: shihong.zheng <shihong.zheng@amlogic.com>
Diffstat
-rw-r--r--drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c1114
-rw-r--r--drivers/frame_provider/decoder/utils/amvdec.c18
-rw-r--r--firmware/video_ucode.bin104
3 files changed, 663 insertions, 573 deletions
diff --git a/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c b/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c
index b6f4a9f..224d366 100644
--- a/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c
+++ b/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c
@@ -71,17 +71,17 @@
#define MREG_WAIT_BUFFER AV_SCRATCH_E
#define MREG_FATAL_ERROR AV_SCRATCH_F
+#define GET_SLICE_TYPE(type) ("IPB##"[((type&PICINFO_TYPE_MASK)>>16)&0x3])
#define PICINFO_ERROR 0x80000000
#define PICINFO_TYPE_MASK 0x00030000
#define PICINFO_TYPE_I 0x00000000
#define PICINFO_TYPE_P 0x00010000
#define PICINFO_TYPE_B 0x00020000
-
-#define GET_SLICE_TYPE(type) ("IPB###"[(type&PICINFO_TYPE_MASK)>>16])
#define PICINFO_PROG 0x8000
#define PICINFO_RPT_FIRST 0x4000
#define PICINFO_TOP_FIRST 0x2000
#define PICINFO_FRAME 0x1000
+
#define TOP_FIELD 0x1000
#define BOTTOM_FIELD 0x2000
#define FRAME_PICTURE 0x3000
@@ -105,17 +105,20 @@
#define DEFAULT_MEM_SIZE (32*SZ_1M)
static u32 buf_size = 32 * 1024 * 1024;
static int pre_decode_buf_level = 0x800;
+static int start_decode_buf_level = 0x4000;
static u32 dec_control;
-static u32 error_frame_skip_level;
+static u32 error_frame_skip_level = 2;
static u32 stat;
static u32 udebug_flag;
static unsigned int radr;
static unsigned int rval;
+static u32 without_display_mode;
+
#define VMPEG12_DEV_NUM 9
static unsigned int max_decode_instance_num = VMPEG12_DEV_NUM;
static unsigned int max_process_time[VMPEG12_DEV_NUM];
-static unsigned int decode_timeout_val = 100;
+static unsigned int decode_timeout_val = 200;
#define INCPTR(p) ptr_atomic_wrap_inc(&p)
#define DEC_CONTROL_FLAG_FORCE_2500_720_576_INTERLACE 0x0002
@@ -132,6 +135,15 @@ static unsigned int decode_timeout_val = 100;
#define NV21
#endif
+#define AGAIN_HAS_THRESHOLD
+
+#ifdef AGAIN_HAS_THRESHOLD
+u32 again_threshold;
+#endif
+
+/*
+#define DUMP_USER_DATA
+*/
enum {
FRAME_REPEAT_TOP,
@@ -156,6 +168,16 @@ static struct vframe_s *vmpeg_vf_get(void *);
static void vmpeg_vf_put(struct vframe_s *, void *);
static int vmpeg_vf_states(struct vframe_states *states, void *);
static int vmpeg_event_cb(int type, void *data, void *private_data);
+struct pic_info_t {
+ u32 buffer_info;
+ u32 index;
+ u32 offset;
+ u32 width;
+ u32 height;
+ u32 pts;
+ u64 pts64;
+ bool pts_valid;
+};
struct vdec_mpeg12_hw_s {
spinlock_t lock;
@@ -164,6 +186,7 @@ struct vdec_mpeg12_hw_s {
DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE);
struct vframe_s vfpool[VF_POOL_SIZE];
s32 vfbuf_use[DECODE_BUFFER_NUM_MAX];
+ s32 ref_use[DECODE_BUFFER_NUM_MAX];
u32 frame_width;
u32 frame_height;
u32 frame_dur;
@@ -186,17 +209,17 @@ struct vdec_mpeg12_hw_s {
u32 reg_vcop_ctrl_reg;
u32 reg_mb_info;
u32 reg_signal_type;
- u32 frame_num;
+ u32 dec_num;
+ u32 disp_num;
struct timer_list check_timer;
u32 decode_timeout_count;
- u32 start_process_time;
+ unsigned long int start_process_time;
u32 last_vld_level;
u32 eos;
- u32 buffer_info[DECODE_BUFFER_NUM_MAX];
- u32 pts[DECODE_BUFFER_NUM_MAX];
- u64 pts64[DECODE_BUFFER_NUM_MAX];
- bool pts_valid[DECODE_BUFFER_NUM_MAX];
+ struct pic_info_t pics[DECODE_BUFFER_NUM_MAX];
u32 canvas_spec[DECODE_BUFFER_NUM_MAX];
+ u64 lastpts64;
+ u32 last_chunk_pts;
struct canvas_config_s canvas_config[DECODE_BUFFER_NUM_MAX][2];
struct dec_sysinfo vmpeg12_amstream_dec_info;
@@ -223,8 +246,16 @@ struct vdec_mpeg12_hw_s {
u32 get_num;
u32 drop_frame_count;
u32 buffer_not_ready;
+ u32 ratio_control;
int frameinfo_enable;
struct firmware_s *fw;
+ u32 canvas_mode;
+#ifdef AGAIN_HAS_THRESHOLD
+ u32 pre_parser_wr_ptr;
+ u8 next_again_flag;
+#endif
+ u32 userdata_wp_ctx;
+ int tvp_flag;
};
static void vmpeg12_local_init(struct vdec_mpeg12_hw_s *hw);
static int vmpeg12_hw_ctx_restore(struct vdec_mpeg12_hw_s *hw);
@@ -251,6 +282,9 @@ unsigned int mpeg12_debug_mask = 0xff;
#define PRINT_FRAMEBASE_DATA 0x0400
#define PRINT_FLAG_VDEC_STATUS 0x0800
#define PRINT_FLAG_PARA_DATA 0x1000
+#define PRINT_FLAG_USERDATA_DETAIL 0x2000
+#define PRINT_FLAG_TIMEOUT_STATUS 0x4000
+
int debug_print(int index, int debug_flag, const char *fmt, ...)
@@ -297,7 +331,7 @@ static u32 find_buffer(struct vdec_mpeg12_hw_s *hw)
u32 i;
for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) {
- if (hw->vfbuf_use[i] == 0)
+ if ((hw->vfbuf_use[i] == 0) && (hw->ref_use[i] == 0))
return i;
}
@@ -318,31 +352,18 @@ static u32 spec_to_index(struct vdec_mpeg12_hw_s *hw, u32 spec)
static void set_frame_info(struct vdec_mpeg12_hw_s *hw, struct vframe_s *vf)
{
- unsigned ar_bits;
- u32 temp;
+ u32 ar_bits;
u32 buffer_index = vf->index;
-#ifdef CONFIG_AM_VDEC_MPEG12_LOG
- bool first = (hw->frame_width == 0) && (hw->frame_height == 0);
-#endif
- temp = READ_VREG(MREG_PIC_WIDTH);
- if (temp > 1920 || temp == 0)
- vf->width = hw->frame_width = 1920;
- else
- vf->width = hw->frame_width = temp;
-
- temp = READ_VREG(MREG_PIC_HEIGHT);
- if (temp > 1088 || temp == 0)
- vf->height = hw->frame_height = 1088;
- else
- vf->height = hw->frame_height = temp;
+ vf->width = hw->pics[buffer_index].width;
+ vf->height = hw->pics[buffer_index].height;
if (hw->frame_dur > 0)
vf->duration = hw->frame_dur;
else {
vf->duration = hw->frame_dur =
frame_rate_tab[(READ_VREG(MREG_SEQ_INFO) >> 4) & 0xf];
- schedule_work(&hw->notify_work);
+ vdec_schedule_work(&hw->notify_work);
}
ar_bits = READ_VREG(MREG_SEQ_INFO) & 0xf;
@@ -358,6 +379,8 @@ static void set_frame_info(struct vdec_mpeg12_hw_s *hw, struct vframe_s *vf)
else
vf->ratio_control = 0;
+ hw->ratio_control = vf->ratio_control;
+
vf->canvas0Addr = vf->canvas1Addr = -1;
vf->plane_num = 2;
@@ -367,7 +390,6 @@ static void set_frame_info(struct vdec_mpeg12_hw_s *hw, struct vframe_s *vf)
vf->canvas1_config[0] = hw->canvas_config[buffer_index][0];
vf->canvas1_config[1] = hw->canvas_config[buffer_index][1];
-
debug_print(DECODE_ID(hw), PRINT_FLAG_PARA_DATA,
"mpeg2dec: w(%d), h(%d), dur(%d), dur-ES(%d)\n",
hw->frame_width, hw->frame_height, hw->frame_dur,
@@ -396,20 +418,26 @@ static bool error_skip(struct vdec_mpeg12_hw_s *hw,
return false;
}
-static inline void vmpeg12_save_hw_context(struct vdec_mpeg12_hw_s *hw)
+static inline void vmpeg12_save_hw_context(struct vdec_mpeg12_hw_s *hw, u32 reg)
{
- hw->seqinfo = READ_VREG(MREG_SEQ_INFO);
- hw->reg_pic_width = READ_VREG(MREG_PIC_WIDTH);
- hw->reg_pic_height = READ_VREG(MREG_PIC_HEIGHT);
- hw->reg_mpeg1_2_reg = READ_VREG(MPEG1_2_REG);
- hw->reg_pic_head_info = READ_VREG(PIC_HEAD_INFO);
- hw->reg_f_code_reg = READ_VREG(F_CODE_REG);
- hw->reg_slice_ver_pos_pic_type = READ_VREG(SLICE_VER_POS_PIC_TYPE);
- hw->reg_vcop_ctrl_reg = READ_VREG(VCOP_CTRL_REG);
- hw->reg_mb_info = READ_VREG(MB_INFO);
- hw->reg_signal_type = READ_VREG(AV_SCRATCH_H);
- debug_print(DECODE_ID(hw), PRINT_FLAG_PARA_DATA,
- "signal_type = %x", hw->reg_signal_type);
+ if (reg == 3) {
+ hw->ctx_valid = 0;
+ //pr_info("%s, hw->userdata_wp_ctx %d\n", __func__, hw->userdata_wp_ctx);
+ } else {
+ hw->seqinfo = READ_VREG(MREG_SEQ_INFO);
+ hw->reg_pic_width = READ_VREG(MREG_PIC_WIDTH);
+ hw->reg_pic_height = READ_VREG(MREG_PIC_HEIGHT);
+ hw->reg_mpeg1_2_reg = READ_VREG(MPEG1_2_REG);
+ hw->reg_pic_head_info = READ_VREG(PIC_HEAD_INFO);
+ hw->reg_f_code_reg = READ_VREG(F_CODE_REG);
+ hw->reg_slice_ver_pos_pic_type = READ_VREG(SLICE_VER_POS_PIC_TYPE);
+ hw->reg_vcop_ctrl_reg = READ_VREG(VCOP_CTRL_REG);
+ hw->reg_mb_info = READ_VREG(MB_INFO);
+ hw->reg_signal_type = READ_VREG(AV_SCRATCH_H);
+ debug_print(DECODE_ID(hw), PRINT_FLAG_PARA_DATA,
+ "signal_type = %x", hw->reg_signal_type);
+ hw->ctx_valid = 1;
+ }
}
#if 0
static void userdata_push_do_work(struct work_struct *work)
@@ -440,14 +468,210 @@ static void userdata_push_do_work(struct work_struct *work)
WRITE_VREG(MREG_BUFFEROUT, 0);
}
#endif
-static irqreturn_t vmpeg12_isr_thread_fn(struct vdec_s *vdec, int irq)
+
+static int prepare_display_buf(struct vdec_mpeg12_hw_s *hw,
+ struct pic_info_t *pic)
{
- u32 reg, info, seqinfo, offset, pts, pts_valid = 0;
+ u32 field_num = 0, i;
+ u32 first_field_type = 0, type = 0;
struct vframe_s *vf = NULL;
- u32 index;
+ u32 index = pic->index;
+ u32 info = pic->buffer_info;
+ struct vdec_s *vdec = hw_to_vdec(hw);
+
+ if (hw == NULL || pic == NULL)
+ return -1;
+
+ /*user_data_ready_notify(hw, pic->pts, pic->pts_valid);*/
+#ifdef NV21
+ type = VIDTYPE_VIU_NV21;
+#endif
+
+ if (hw->frame_prog & PICINFO_PROG) {
+ field_num = 1;
+ type |= VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD;
+ } else {
+#ifdef INTERLACE_SEQ_ALWAYS
+ /* once an interlace seq, force interlace, to make di easy. */
+ hw->dec_control |= DEC_CONTROL_FLAG_FORCE_SEQ_INTERLACE;
+#endif
+ hw->frame_rpt_state = FRAME_REPEAT_NONE;
+
+ first_field_type = (info & PICINFO_TOP_FIRST) ?
+ VIDTYPE_INTERLACE_TOP : VIDTYPE_INTERLACE_BOTTOM;
+ field_num = (info & PICINFO_RPT_FIRST) ? 3 : 2;
+ }
+
+ for (i = 0; i < field_num; i++) {
+ if (kfifo_get(&hw->newframe_q, &vf) == 0) {
+ debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR,
+ "fatal error, no available buffer slot.");
+ hw->dec_result = DEC_RESULT_ERROR;
+ vdec_schedule_work(&hw->work);
+ return -1;
+ }
+ hw->vfbuf_use[index]++;
+ vf->index = index;
+ set_frame_info(hw, vf);
+ if (field_num > 1) {
+ vf->duration = vf->duration / field_num;
+ vf->duration_pulldown = (field_num == 3) ?
+ (vf->duration >> 1):0;
+ if (i > 0)
+ type = VIDTYPE_VIU_NV21;
+ if (i == 1) /* second field*/
+ type |= (first_field_type == VIDTYPE_INTERLACE_TOP) ?
+ VIDTYPE_INTERLACE_BOTTOM : VIDTYPE_INTERLACE_TOP;
+ else
+ type |= (first_field_type == VIDTYPE_INTERLACE_TOP) ?
+ VIDTYPE_INTERLACE_TOP : VIDTYPE_INTERLACE_BOTTOM;
+ } else {
+ if ((hw->seqinfo & SEQINFO_EXT_AVAILABLE) &&
+ (hw->seqinfo & SEQINFO_PROG)) {
+ if (info & PICINFO_RPT_FIRST) {
+ if (info & PICINFO_TOP_FIRST)
+ vf->duration *= 3;
+ else
+ vf->duration *= 2;
+ }
+ vf->duration_pulldown = 0;
+ } else {
+ vf->duration_pulldown =
+ (info & PICINFO_RPT_FIRST) ?
+ vf->duration >> 1 : 0;
+ }
+ }
+ vf->duration += vf->duration_pulldown;
+ vf->type = type;
+ vf->signal_type = hw->reg_signal_type;
+ vf->orientation = 0;
+ if (i > 0) {
+ vf->pts = 0;
+ vf->pts_us64 = 0;
+ } else {
+ vf->pts = (pic->pts_valid) ? pic->pts : 0;
+ vf->pts_us64 = (pic->pts_valid) ? pic->pts64 : 0;
+ }
+ vf->type_original = vf->type;
+
+ if ((error_skip(hw, pic->buffer_info, vf)) ||
+ ((hw->first_i_frame_ready == 0) &&
+ ((PICINFO_TYPE_MASK & pic->buffer_info) !=
+ PICINFO_TYPE_I))) {
+ hw->drop_frame_count++;
+ hw->vfbuf_use[index]--;
+ kfifo_put(&hw->newframe_q,
+ (const struct vframe_s *)vf);
+ } else {
+ debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO,
+ "%s, vf: %p, num[%d]: %d(%c), dur: %d, type: %x, pts: %d(%lld)\n",
+ __func__, vf, i, hw->disp_num, GET_SLICE_TYPE(info),
+ vf->duration, vf->type, vf->pts, vf->pts_us64);
+ hw->disp_num++;
+ /*
+ if (i == 0)
+ decoder_do_frame_check(hw_to_vdec(hw), vf);
+ vdec->vdec_fps_detec(vdec->id);
+ */
+ vf->mem_handle =
+ decoder_bmmu_box_get_mem_handle(
+ hw->mm_blk_handle, index);
+ /*pr_info("%s: vf %p, index %d, use %d\n", __func__,
+ vf, index, hw->vfbuf_use[index]);*/
+ kfifo_put(&hw->display_q,
+ (const struct vframe_s *)vf);
+ if (without_display_mode == 0) {
+ vf_notify_receiver(vdec->vf_provider_name,
+ VFRAME_EVENT_PROVIDER_VFRAME_READY,
+ NULL);
+ } else
+ vmpeg_vf_put(vmpeg_vf_get(vdec), vdec);
+
+
+ }
+ }
+ return 0;
+}
+
+static void force_interlace_check(struct vdec_mpeg12_hw_s *hw)
+{
+ if ((hw->dec_control &
+ DEC_CONTROL_FLAG_FORCE_2500_720_576_INTERLACE) &&
+ (hw->frame_width == 720) &&
+ (hw->frame_height == 576) &&
+ (hw->frame_dur == 3840)) {
+ hw->frame_prog = 0;
+ } else if ((hw->dec_control
+ & DEC_CONTROL_FLAG_FORCE_3000_704_480_INTERLACE) &&
+ (hw->frame_width == 704) &&
+ (hw->frame_height == 480) &&
+ (hw->frame_dur == 3200)) {
+ hw->frame_prog = 0;
+ } else if ((hw->dec_control
+ & DEC_CONTROL_FLAG_FORCE_2500_704_576_INTERLACE) &&
+ (hw->frame_width == 704) &&
+ (hw->frame_height == 576) &&
+ (hw->frame_dur == 3840)) {
+ hw->frame_prog = 0;
+ } else if ((hw->dec_control
+ & DEC_CONTROL_FLAG_FORCE_2500_544_576_INTERLACE) &&
+ (hw->frame_width == 544) &&
+ (hw->frame_height == 576) &&
+ (hw->frame_dur == 3840)) {
+ hw->frame_prog = 0;
+ } else if ((hw->dec_control
+ & DEC_CONTROL_FLAG_FORCE_2500_480_576_INTERLACE) &&
+ (hw->frame_width == 480) &&
+ (hw->frame_height == 576) &&
+ (hw->frame_dur == 3840)) {
+ hw->frame_prog = 0;
+ } else if (hw->dec_control
+ & DEC_CONTROL_FLAG_FORCE_SEQ_INTERLACE) {
+ hw->frame_prog = 0;
+ }
+
+}
+
+static int update_reference(struct vdec_mpeg12_hw_s *hw,
+ int index)
+{
+ hw->ref_use[index]++;
+ if (hw->refs[1] == -1) {
+ hw->refs[1] = index;
+ /*
+ * first pic need output to show
+ * usecnt do not decrease.
+ */
+ } else if (hw->refs[0] == -1) {
+ hw->refs[0] = hw->refs[1];
+ hw->refs[1] = index;
+ /* second pic do not output */
+ index = DECODE_BUFFER_NUM_MAX;
+ } else {
+ hw->ref_use[hw->refs[0]]--;
+ hw->refs[0] = hw->refs[1];
+ hw->refs[1] = index;
+ index = hw->refs[0];
+ }
+ return index;
+}
+
+static bool is_ref_error(struct vdec_mpeg12_hw_s *hw)
+{
+ if ((hw->pics[hw->refs[0]].buffer_info & PICINFO_ERROR) ||
+ (hw->pics[hw->refs[1]].buffer_info & PICINFO_ERROR))
+ return 1;
+ return 0;
+}
+
+
+static irqreturn_t vmpeg12_isr_thread_fn(struct vdec_s *vdec, int irq)
+{
+ u32 reg, index, info, seqinfo, offset, pts, tmp;
u64 pts_us64 = 0;
+ struct pic_info_t *new_pic, *disp_pic;
struct vdec_mpeg12_hw_s *hw =
- (struct vdec_mpeg12_hw_s *)(vdec->private);
+ (struct vdec_mpeg12_hw_s *)(vdec->private);
if (READ_VREG(AV_SCRATCH_M) != 0 &&
(debug_enable & PRINT_FLAG_UCODE_DETAIL)) {
@@ -463,429 +687,158 @@ static irqreturn_t vmpeg12_isr_thread_fn(struct vdec_s *vdec, int irq)
return IRQ_HANDLED;
}
- reg = READ_VREG(MREG_BUFFEROUT);
+ reg = READ_VREG(AV_SCRATCH_J);
+ if (reg & (1<<16)) {
+ /*vdec_schedule_work(&hw->userdata_push_work);*/
+ WRITE_VREG(AV_SCRATCH_J, 0);
+ return IRQ_HANDLED;
+ }
- if ((reg >> 16) == 0xfe) {
- /*pr_info("%s,%d\n",__func__,__LINE__);*/
- /*vdec_schedule_work(&userdata_push_work);*/
- WRITE_VREG(MREG_BUFFEROUT, 0);
- } else if (reg == 2) {
+ reg = READ_VREG(MREG_BUFFEROUT);
+ if (reg == 2) {
/*timeout when decoding next frame*/
-
- debug_print(DECODE_ID(hw), PRINT_FLAG_VLD_DETAIL,
- "ammvdec_mpeg12: Insufficient data\n");
debug_print(DECODE_ID(hw), PRINT_FLAG_VLD_DETAIL,
- "level=%x, vtl=%x,bcnt=%d\n",
- READ_VREG(VLD_MEM_VIFIFO_LEVEL),
- READ_VREG(VLD_MEM_VIFIFO_CONTROL),
- READ_VREG(VIFF_BIT_CNT));
- if (input_frame_based(vdec))
- vmpeg12_save_hw_context(hw);
- else {
+ "mmpeg12: lack data, lvl=%x ctrl=%x bcnt=%x\n",
+ READ_VREG(VLD_MEM_VIFIFO_LEVEL),
+ READ_VREG(VLD_MEM_VIFIFO_CONTROL),
+ READ_VREG(VIFF_BIT_CNT));
+
+ if (vdec_frame_based(vdec)) {
+ /* vmpeg12_save_hw_context(hw); */
+ reset_process_time(hw);
+ hw->dec_result = DEC_RESULT_DONE;
+ vdec_schedule_work(&hw->work);
+ } else {
hw->dec_result = DEC_RESULT_AGAIN;
vdec_schedule_work(&hw->work);
+ /*userdata_pushed_drop(hw);*/
+ reset_process_time(hw);
}
return IRQ_HANDLED;
} else {
reset_process_time(hw);
+
info = READ_VREG(MREG_PIC_INFO);
offset = READ_VREG(MREG_FRAME_OFFSET);
index = spec_to_index(hw, READ_VREG(REC_CANVAS_ADDR));
seqinfo = READ_VREG(MREG_SEQ_INFO);
+
if ((info & PICINFO_PROG) == 0 &&
- (info & FRAME_PICTURE_MASK) != FRAME_PICTURE)
+ (info & FRAME_PICTURE_MASK) != FRAME_PICTURE)
hw->first_i_frame_ready = 1; /* for field struct case*/
- debug_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL,
- "struct: %d %x\n", (info & PICINFO_FRAME), info);
- if (index >= DECODE_BUFFER_NUM_MAX) {
+ if (index >= DECODE_BUFFER_NUM_MAX) {
debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR,
- "invalid buffer index,index=%d\n",
- index);
+ "mmpeg12: invalid buf index: %d\n", index);
hw->dec_result = DEC_RESULT_ERROR;
vdec_schedule_work(&hw->work);
return IRQ_HANDLED;
}
-
+ hw->dec_num++;
hw->dec_result = DEC_RESULT_DONE;
+ new_pic = &hw->pics[index];
+ tmp = READ_VREG(MREG_PIC_WIDTH);
+ if ((tmp > 1920) || (tmp == 0)) {
+ new_pic->width = 1920;
+ hw->frame_width = 1920;
+ } else {
+ new_pic->width = tmp;
+ hw->frame_width = tmp;
+ }
- /*debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO,
- "ammvdec_mpeg12: error = 0x%x, offset = 0x%x\n",
- info & PICINFO_ERROR, offset);*/
+ tmp = READ_VREG(MREG_PIC_HEIGHT);
+ if ((tmp > 1088) || (tmp == 0)) {
+ new_pic->height = 1088;
+ hw->frame_height = 1088;
+ } else {
+ new_pic->height = tmp;
+ hw->frame_height = tmp;
+ }
+ new_pic->buffer_info = info;
+ new_pic->offset = offset;
+ new_pic->index = index;
if (((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_I) ||
((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_P)) {
if (hw->chunk) {
- hw->pts_valid[index] = hw->chunk->pts_valid;
- hw->pts[index] = hw->chunk->pts;
- hw->pts64[index] = hw->chunk->pts64;
-
- debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO,
- "!!!cpts=%d,pts64=%lld,size=%d,offset=%d\n",
- hw->pts[index], hw->pts64[index],
- hw->chunk->size, hw->chunk->offset);
- } else {
- if (pts_lookup_offset_us64(PTS_TYPE_VIDEO,
- offset, &pts, 0, &pts_us64) == 0) {
- hw->pts_valid[index] = true;
- hw->pts[index] = pts;
- hw->pts64[index] = pts_us64;
- } else {
- hw->pts_valid[index] = false;
+ new_pic->pts_valid = hw->chunk->pts_valid;
+ new_pic->pts = hw->chunk->pts;
+ new_pic->pts64 = hw->chunk->pts64;
+ if (hw->last_chunk_pts == hw->chunk->pts) {
+ new_pic->pts_valid = 0;
+ debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO,
+ "pts invalid\n");
}
+ } else {
+ if (pts_lookup_offset_us64(PTS_TYPE_VIDEO, offset,
+ &pts, 0, &pts_us64) == 0) {
+ new_pic->pts_valid = true;
+ new_pic->pts = pts;
+ new_pic->pts64 = pts_us64;
+ } else
+ new_pic->pts_valid = false;
}
} else {
- hw->pts_valid[index] = false;
- }
- /*if (frame_prog == 0) */
- {
- hw->frame_prog = info & PICINFO_PROG;
- if ((seqinfo & SEQINFO_EXT_AVAILABLE)
- && (!(seqinfo & SEQINFO_PROG)))
- hw->frame_prog = 0;
- }
- if ((hw->dec_control &
- DEC_CONTROL_FLAG_FORCE_2500_720_576_INTERLACE) &&
- (hw->frame_width == 720) &&
- (hw->frame_height == 576) &&
- (hw->frame_dur == 3840)) {
- hw->frame_prog = 0;
- } else if ((hw->dec_control
- & DEC_CONTROL_FLAG_FORCE_3000_704_480_INTERLACE) &&
- (hw->frame_width == 704) &&
- (hw->frame_height == 480) &&
- (hw->frame_dur == 3200)) {
- hw->frame_prog = 0;
- } else if ((hw->dec_control
- & DEC_CONTROL_FLAG_FORCE_2500_704_576_INTERLACE) &&
- (hw->frame_width == 704) &&
- (hw->frame_height == 576) &&
- (hw->frame_dur == 3840)) {
- hw->frame_prog = 0;
- } else if ((hw->dec_control
- & DEC_CONTROL_FLAG_FORCE_2500_544_576_INTERLACE) &&
- (hw->frame_width == 544) &&
- (hw->frame_height == 576) &&
- (hw->frame_dur == 3840)) {
- hw->frame_prog = 0;
- } else if ((hw->dec_control
- & DEC_CONTROL_FLAG_FORCE_2500_480_576_INTERLACE) &&
- (hw->frame_width == 480) &&
- (hw->frame_height == 576) &&
- (hw->frame_dur == 3840)) {
- hw->frame_prog = 0;
- } else if (hw->dec_control
- & DEC_CONTROL_FLAG_FORCE_SEQ_INTERLACE) {
- hw->frame_prog = 0;
+ if (hw->chunk)
+ hw->last_chunk_pts = hw->chunk->pts;
+ new_pic->pts_valid = false;
}
- hw->buffer_info[index] = info;
+ debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW,
+ "mmpeg12: new_pic=%d, ind=%d, info=%x, seq=%x, offset=%d\n",
+ hw->dec_num, index, info, seqinfo, offset);
- debug_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL,
- "ammvdec_mpeg12: decoded buffer %d, frame_type %c\n",
- index, GET_SLICE_TYPE(info));
+ hw->frame_prog = info & PICINFO_PROG;
+ if ((seqinfo & SEQINFO_EXT_AVAILABLE) &&
+ ((seqinfo & SEQINFO_PROG) == 0))
+ hw->frame_prog = 0;
+ force_interlace_check(hw);
+
+ if (is_ref_error(hw)) {
+ if ((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_B)
+ new_pic->buffer_info |= PICINFO_ERROR;
+ }
- /* Buffer management
- todo: add sequence-end flush */
if (((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_I) ||
((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_P)) {
- hw->vfbuf_use[index]++;
- if (hw->refs[1] == -1) {
- hw->refs[1] = index;
- index = DECODE_BUFFER_NUM_MAX;
- } else if (hw->refs[0] == -1) {
- hw->refs[0] = hw->refs[1];
- hw->refs[1] = index;
- index = hw->refs[0];
- } else {
- hw->vfbuf_use[hw->refs[0]]--;
- hw->refs[0] = hw->refs[1];
- hw->refs[1] = index;
- index = hw->refs[0];
- }
+ index = update_reference(hw, index);
} else {
- /* if this is a B frame, then drop
- (depending on if there are two reference frames)
- or display immediately*/
+ /* drop b frame before reference pic ready */
if (hw->refs[0] == -1)
index = DECODE_BUFFER_NUM_MAX;
-
}
-
- vmpeg12_save_hw_context(hw);
+ vmpeg12_save_hw_context(hw, reg);
if (index >= DECODE_BUFFER_NUM_MAX) {
- debug_print(DECODE_ID(hw), 0,
- "invalid buffer index,index=%d\n", index);
- hw->dec_result = DEC_RESULT_ERROR;
+ if (hw->dec_num != 2) {
+ debug_print(DECODE_ID(hw), 0,
+ "mmpeg12: drop pic num %d, type %c, index %d, offset %x\n",
+ hw->dec_num, GET_SLICE_TYPE(info), index, offset);
+ hw->dec_result = DEC_RESULT_ERROR;
+ }
vdec_schedule_work(&hw->work);
return IRQ_HANDLED;
}
- info = hw->buffer_info[index];
- pts_valid = hw->pts_valid[index];
- pts = hw->pts[index];
- pts_us64 = hw->pts64[index];
+ disp_pic = &hw->pics[index];
+ info = hw->pics[index].buffer_info;
+ if (disp_pic->pts_valid && hw->lastpts64 == disp_pic->pts64)
+ disp_pic->pts_valid = false;
+ if (disp_pic->pts_valid)
+ hw->lastpts64 = disp_pic->pts64;
if ((hw->first_i_frame_ready == 0) &&
((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_I) &&
((info & PICINFO_ERROR) == 0))
hw->first_i_frame_ready = 1;
- debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW,
- "ammvdec_mpeg12: display buffer %d, frame_type %c\n",
- index, GET_SLICE_TYPE(info));
- if (hw->frame_prog & PICINFO_PROG) {
-
- seqinfo = READ_VREG(MREG_SEQ_INFO);
-
- if (kfifo_get(&hw->newframe_q, &vf) == 0) {
- debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR,
- "fatal error, no available buffer slot.");
- hw->dec_result = DEC_RESULT_ERROR;
- vdec_schedule_work(&hw->work);
-
- return IRQ_HANDLED;
- }
-
- vf->index = index;
- set_frame_info(hw, vf);
- vf->signal_type = hw->reg_signal_type;
-
-#ifdef NV21
- vf->type =
- VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD |
- VIDTYPE_VIU_NV21;
-#else
- vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD;
-#endif
- if ((hw->seqinfo & SEQINFO_EXT_AVAILABLE)
- && (hw->seqinfo & SEQINFO_PROG)) {
- if (info & PICINFO_RPT_FIRST) {
- if (info & PICINFO_TOP_FIRST) {
- vf->duration =
- vf->duration * 3;
- /* repeat three times */
- } else {
- vf->duration =
- vf->duration * 2;
- /* repeat two times */
- }
- }
- vf->duration_pulldown = 0;
- /* no pull down */
-
- } else {
- vf->duration_pulldown =
- (info & PICINFO_RPT_FIRST) ?
- vf->duration >> 1 : 0;
- }
-
- vf->duration += vf->duration_pulldown;
-
- vf->orientation = 0;
- vf->pts = (pts_valid) ? pts : 0;
- vf->pts_us64 = (pts_valid) ? pts_us64 : 0;
- vf->type_original = vf->type;
- hw->vfbuf_use[index]++;
-
- if ((error_skip(hw, info, vf)) ||
- ((hw->first_i_frame_ready == 0)
- && ((PICINFO_TYPE_MASK & info) !=
- PICINFO_TYPE_I))) {
- hw->drop_frame_count++;
- hw->vfbuf_use[index]--;
- kfifo_put(&hw->newframe_q,
- (const struct vframe_s *)vf);
-
- } else {
- debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO,
- "cpts=%d,pts64=%lld\n",
- vf->pts, vf->pts_us64);
- kfifo_put(&hw->display_q,
- (const struct vframe_s *)vf);
- hw->frame_num++;
- vf_notify_receiver(vdec->vf_provider_name,
- VFRAME_EVENT_PROVIDER_VFRAME_READY,
- NULL);
- }
- }
-/*interlace temp*/
- else {
- int first_field_type = (info & PICINFO_TOP_FIRST) ?
- VIDTYPE_INTERLACE_TOP :
- VIDTYPE_INTERLACE_BOTTOM;
-
-#ifdef INTERLACE_SEQ_ALWAYS
- /* once an interlaced sequence exist,
- always force interlaced type */
- /* to make DI easy. */
- hw->dec_control |= DEC_CONTROL_FLAG_FORCE_SEQ_INTERLACE;
-#endif
-
- hw->frame_rpt_state = FRAME_REPEAT_NONE;
-
- if (kfifo_get(&hw->newframe_q, &vf) == 0) {
- debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR,
- "fatal error, no available buffer slot.");
- vdec_schedule_work(&hw->work);
- return IRQ_HANDLED;
- }
-
- hw->vfbuf_use[index] += 2;
- vf->signal_type = hw->reg_signal_type;
- vf->index = index;
- set_frame_info(hw, vf);
- vf->type =
- (first_field_type == VIDTYPE_INTERLACE_TOP) ?
- VIDTYPE_INTERLACE_TOP :
- VIDTYPE_INTERLACE_BOTTOM;
-#ifdef NV21
- vf->type |= VIDTYPE_VIU_NV21;
-#endif
- if (info & PICINFO_RPT_FIRST)
- vf->duration /= 3;
- else
- vf->duration >>= 1;
- vf->duration_pulldown = (info & PICINFO_RPT_FIRST) ?
- vf->duration >> 1 : 0;
- vf->duration += vf->duration_pulldown;
- vf->orientation = 0;
- vf->pts = (pts_valid) ? pts : 0;
- vf->pts_us64 = (pts_valid) ? pts_us64 : 0;
-
- if ((error_skip(hw, info, vf)) ||
- ((hw->first_i_frame_ready == 0)
- && ((PICINFO_TYPE_MASK & info) !=
- PICINFO_TYPE_I))) {
- hw->vfbuf_use[index]--;
- hw->drop_frame_count++;
- kfifo_put(&hw->newframe_q,
- (const struct vframe_s *)vf);
- } else {
- debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO,
- "cpts0=%d,pts64=%lld,dur=%d, index %d , use %d\n",
- vf->pts, vf->pts_us64, vf->duration,
- vf->index, hw->vfbuf_use[index]);
- kfifo_put(&hw->display_q,
- (const struct vframe_s *)vf);
- hw->frame_num++;
- vf_notify_receiver(vdec->vf_provider_name,
- VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
- }
-
- if (kfifo_get(&hw->newframe_q, &vf) == 0) {
- debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR,
- "ammvdec_mpeg12: fatal error, no available buffer slot.");
-
- hw->vfbuf_use[index]--;
-
- vdec_schedule_work(&hw->work);
-
- return IRQ_HANDLED;
- }
- vf->signal_type = hw->reg_signal_type;
- vf->index = index;
- set_frame_info(hw, vf);
- vf->type = (first_field_type ==
- VIDTYPE_INTERLACE_TOP) ?
- VIDTYPE_INTERLACE_BOTTOM :
- VIDTYPE_INTERLACE_TOP;
-#ifdef NV21
- vf->type |= VIDTYPE_VIU_NV21;
-#endif
- if (info & PICINFO_RPT_FIRST)
- vf->duration /= 3;
- else
- vf->duration >>= 1;
- vf->duration_pulldown = (info & PICINFO_RPT_FIRST) ?
- vf->duration >> 1 : 0;
- vf->duration += vf->duration_pulldown;
- vf->orientation = 0;
- vf->pts = 0;
- vf->pts_us64 = 0;
- vf->type_original = vf->type;
- if ((error_skip(hw, info, vf)) ||
- ((hw->first_i_frame_ready == 0)
- && ((PICINFO_TYPE_MASK & info) !=
- PICINFO_TYPE_I))) {
- hw->drop_frame_count++;
- hw->vfbuf_use[index]--;
-
- kfifo_put(&hw->newframe_q,
- (const struct vframe_s *)vf);
- } else {
- debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO,
- "cpts1=%d,pts64=%lld,dur=%d index %d, used %d\n",
- vf->pts, vf->pts_us64, vf->duration, vf->index,
- hw->vfbuf_use[index]);
- kfifo_put(&hw->display_q,
- (const struct vframe_s *)vf);
- hw->frame_num++;
- vf_notify_receiver(vdec->vf_provider_name,
- VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
- }
+ debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW,
+ "mmpeg12: disp_pic=%d(%c), ind=%d, offst=%x, pts=(%d,%lld)(%d)\n",
+ hw->disp_num, GET_SLICE_TYPE(info), index, disp_pic->offset,
+ disp_pic->pts, disp_pic->pts64, disp_pic->pts_valid);
- if (info & PICINFO_RPT_FIRST) {
- if (kfifo_get(&hw->newframe_q, &vf) == 0) {
- debug_print(DECODE_ID(hw),
- PRINT_FLAG_ERROR,
- "error, no available buffer slot.");
- return IRQ_HANDLED;
- }
- hw->vfbuf_use[index]++;
- vf->index = index;
- set_frame_info(hw, vf);
- vf->type = (first_field_type ==
- VIDTYPE_INTERLACE_TOP) ?
- VIDTYPE_INTERLACE_TOP :
- VIDTYPE_INTERLACE_BOTTOM;
-#ifdef NV21
- vf->type |= VIDTYPE_VIU_NV21;
-#endif
- vf->duration /= 3;
- vf->duration_pulldown =
- (info & PICINFO_RPT_FIRST) ?
- vf->duration >> 1 : 0;
- vf->duration += vf->duration_pulldown;
- vf->orientation = 0;
-
- vf->pts = 0;
- vf->pts_us64 = 0;
- if ((error_skip(hw, info, vf)) ||
- ((hw->first_i_frame_ready == 0)
- && ((PICINFO_TYPE_MASK & info)
- != PICINFO_TYPE_I))) {
- hw->vfbuf_use[index]--;
- hw->drop_frame_count++;
- kfifo_put(&hw->newframe_q,
- (const struct vframe_s *)vf);
- } else {
- hw->frame_num++;
- debug_print(DECODE_ID(hw),
- PRINT_FLAG_TIMEINFO,
- "cpts2=%d,pts64=%lld,dur=%d index %d, used %d\n",
- vf->pts, vf->pts_us64, vf->duration,
- vf->index, hw->vfbuf_use[index]);
- kfifo_put(&hw->display_q,
- (const struct vframe_s *)vf);
- vf_notify_receiver(
- vdec->vf_provider_name,
- VFRAME_EVENT_PROVIDER_VFRAME_READY,
- NULL);
- }
- }
- }
+ prepare_display_buf(hw, disp_pic);
vdec_schedule_work(&hw->work);
-
- debug_print(DECODE_ID(hw), PRINT_FRAME_NUM,
- "frame_num=%d\n", hw->frame_num);
- if (hw->frame_num == 1)
- debug_print(DECODE_ID(hw), PRINT_FRAME_NUM,
- "frame_num==1\n");
- if (hw->frame_num == 1000)
- debug_print(DECODE_ID(hw), PRINT_FRAME_NUM,
- "frame_num==1000\n");
}
return IRQ_HANDLED;
@@ -894,7 +847,7 @@ static irqreturn_t vmpeg12_isr(struct vdec_s *vdec, int irq)
{
u32 info, offset;
struct vdec_mpeg12_hw_s *hw =
- (struct vdec_mpeg12_hw_s *)(vdec->private);
+ (struct vdec_mpeg12_hw_s *)(vdec->private);
if (hw->eos)
return IRQ_HANDLED;
info = READ_VREG(MREG_PIC_INFO);
@@ -941,87 +894,107 @@ static void wait_vmmpeg12_search_done(struct vdec_mpeg12_hw_s *hw)
} while (1);
}
+static void flush_output(struct vdec_mpeg12_hw_s *hw)
+{
+ int index = hw->refs[1];
+
+ /* video only one frame need not flush. */
+ if (hw->dec_num < 2)
+ return;
+
+ if ((hw->refs[0] >= 0) &&
+ (hw->refs[0] < DECODE_BUFFER_NUM_MAX))
+ hw->ref_use[hw->refs[0]] = 0;
+
+ if (index >= 0 && index < DECODE_BUFFER_NUM_MAX) {
+ hw->ref_use[index] = 0;
+ prepare_display_buf(hw, &hw->pics[index]);
+ }
+}
+
static void vmpeg12_work(struct work_struct *work)
{
struct vdec_mpeg12_hw_s *hw =
container_of(work, struct vdec_mpeg12_hw_s, work);
struct vdec_s *vdec = hw_to_vdec(hw);
+
if (hw->dec_result != DEC_RESULT_DONE)
debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW,
- "ammvdec_mpeg12: vmpeg_work,result=%d,status=%d\n",
- hw->dec_result, hw_to_vdec(hw)->next_status);
+ "%s, result=%d, status=%d\n", __func__,
+ hw->dec_result, vdec->next_status);
if (hw->dec_result == DEC_RESULT_DONE) {
- if (!hw->ctx_valid)
- hw->ctx_valid = 1;
-
- vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk);
- } else if (hw->dec_result == DEC_RESULT_AGAIN
- && (hw_to_vdec(hw)->next_status !=
- VDEC_STATUS_DISCONNECTED)) {
+ vdec_vframe_dirty(vdec, hw->chunk);
+ hw->chunk = NULL;
+ } else if (hw->dec_result == DEC_RESULT_AGAIN &&
+ (vdec->next_status != VDEC_STATUS_DISCONNECTED)) {
/*
stream base: stream buf empty or timeout
frame base: vdec_prepare_input fail
*/
- if (!vdec_has_more_input(hw_to_vdec(hw))) {
+ if (!vdec_has_more_input(vdec)) {
hw->dec_result = DEC_RESULT_EOS;
vdec_schedule_work(&hw->work);
return;
}
- } else if (hw->dec_result == DEC_RESULT_GET_DATA
- && (hw_to_vdec(hw)->next_status !=
- VDEC_STATUS_DISCONNECTED)) {
- if (!vdec_has_more_input(hw_to_vdec(hw))) {
+#ifdef AGAIN_HAS_THRESHOLD
+ hw->next_again_flag = 1;
+#endif
+ } else if (hw->dec_result == DEC_RESULT_GET_DATA &&
+ vdec->next_status != VDEC_STATUS_DISCONNECTED) {
+ if (!vdec_has_more_input(vdec)) {
hw->dec_result = DEC_RESULT_EOS;
vdec_schedule_work(&hw->work);
return;
}
debug_print(DECODE_ID(hw), PRINT_FLAG_VLD_DETAIL,
- "%s DEC_RESULT_GET_DATA %x %x %x\n",
- __func__,
- READ_VREG(VLD_MEM_VIFIFO_LEVEL),
- READ_VREG(VLD_MEM_VIFIFO_WP),
- READ_VREG(VLD_MEM_VIFIFO_RP));
- vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk);
- vdec_clean_input(hw_to_vdec(hw));
+ "%s DEC_RESULT_GET_DATA %x %x %x\n",
+ __func__,
+ READ_VREG(VLD_MEM_VIFIFO_LEVEL),
+ READ_VREG(VLD_MEM_VIFIFO_WP),
+ READ_VREG(VLD_MEM_VIFIFO_RP));
+ vdec_vframe_dirty(vdec, hw->chunk);
+ hw->chunk = NULL;
+ vdec_clean_input(vdec);
return;
} else if (hw->dec_result == DEC_RESULT_FORCE_EXIT) {
debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR,
- "%s: force exit\n", __func__);
+ "%s: force exit\n", __func__);
if (hw->stat & STAT_ISR_REG) {
amvdec_stop();
- /*disable mbox interrupt */
- WRITE_VREG(ASSIST_MBOX1_MASK, 0);
vdec_free_irq(VDEC_IRQ_1, (void *)hw);
hw->stat &= ~STAT_ISR_REG;
}
} else if (hw->dec_result == DEC_RESULT_EOS) {
- pr_info("%s: end of stream\n", __func__);
if (hw->stat & STAT_VDEC_RUN) {
amvdec_stop();
hw->stat &= ~STAT_VDEC_RUN;
}
hw->eos = 1;
- vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk);
- vdec_clean_input(hw_to_vdec(hw));
+ vdec_vframe_dirty(vdec, hw->chunk);
+ hw->chunk = NULL;
+ vdec_clean_input(vdec);
+ flush_output(hw);
+ debug_print(DECODE_ID(hw), 0,
+ "%s: end of stream, num %d(%d)\n",
+ __func__, hw->disp_num, hw->dec_num);
}
if (hw->stat & STAT_VDEC_RUN) {
amvdec_stop();
hw->stat &= ~STAT_VDEC_RUN;
}
+ /*disable mbox interrupt */
+ WRITE_VREG(ASSIST_MBOX1_MASK, 0);
wait_vmmpeg12_search_done(hw);
if (vdec->parallel_dec == 1)
- vdec_core_finish_run(hw_to_vdec(hw), CORE_MASK_VDEC_1);
+ vdec_core_finish_run(vdec, CORE_MASK_VDEC_1);
else
- vdec_core_finish_run(hw_to_vdec(hw), CORE_MASK_VDEC_1 | CORE_MASK_HEVC);
+ vdec_core_finish_run(vdec, CORE_MASK_VDEC_1 | CORE_MASK_HEVC);
del_timer_sync(&hw->check_timer);
hw->stat &= ~STAT_TIMER_ARM;
- if (hw->vdec_cb) {
- hw->vdec_cb(hw_to_vdec(hw), hw->vdec_cb_arg);
- debug_print(DECODE_ID(hw), 0x80000,
- "%s:\n", __func__);
- }
+ if (hw->vdec_cb)
+ hw->vdec_cb(vdec, hw->vdec_cb_arg);
}
static struct vframe_s *vmpeg_vf_peek(void *op_arg)
@@ -1051,15 +1024,48 @@ static struct vframe_s *vmpeg_vf_get(void *op_arg)
return NULL;
}
+static bool vf_valid_check(struct vdec_mpeg12_hw_s *hw,
+ struct vframe_s *vf) {
+ int i;
+
+ if (vf == NULL)
+ return false;
+
+ for (i = 0; i < VF_POOL_SIZE; i++) {
+ if (vf == &hw->vfpool[i])
+ return true;
+ }
+ /*
+ pr_info(" invalid vf been put, vf = %p\n", vf);
+ for (i = 0; i < VF_POOL_SIZE; i++) {
+ pr_info("www valid vf[%d]= %p \n", i, &hw->vfpool[i]);
+ }
+ */
+ return false;
+}
+
static void vmpeg_vf_put(struct vframe_s *vf, void *op_arg)
{
struct vdec_s *vdec = op_arg;
- struct vdec_mpeg12_hw_s *hw =
- (struct vdec_mpeg12_hw_s *)vdec->private;
+ struct vdec_mpeg12_hw_s *hw = NULL;
+
+ if (vdec == NULL)
+ return;
+ hw = (struct vdec_mpeg12_hw_s *)vdec->private;
+
+ if (vf_valid_check(hw, vf) == false) {
+ debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR,
+ "vmpeg_vf_put invalid vf: %p\n", vf);
+ return ;
+ }
+ if (hw->vfbuf_use[vf->index] > 0)
+ hw->vfbuf_use[vf->index]--;
- hw->vfbuf_use[vf->index]--;
hw->put_num++;
- kfifo_put(&hw->newframe_q, (const struct vframe_s *)vf);
+ /*pr_info("%s: vf: %p, index %d, use %d\n", __func__,
+ vf, vf->index, hw->vfbuf_use[vf->index]);*/
+ kfifo_put(&hw->newframe_q,
+ (const struct vframe_s *)vf);
}
static int vmpeg_event_cb(int type, void *data, void *private_data)
@@ -1072,7 +1078,7 @@ static int vmpeg_vf_states(struct vframe_states *states, void *op_arg)
unsigned long flags;
struct vdec_s *vdec = op_arg;
struct vdec_mpeg12_hw_s *hw =
- (struct vdec_mpeg12_hw_s *)vdec->private;
+ (struct vdec_mpeg12_hw_s *)vdec->private;
spin_lock_irqsave(&hw->lock, flags);
@@ -1110,6 +1116,7 @@ static int vmmpeg12_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus)
vstatus->total_data = gvs.total_data;
vstatus->samp_cnt = gvs.samp_cnt;
vstatus->offset = gvs.offset;
+ //vstatus->ratio_control = hw->ratio_control;
snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name),
"%s", DRIVER_NAME);
@@ -1184,28 +1191,29 @@ static void vmpeg12_canvas_init(struct vdec_mpeg12_hw_s *hw)
}
hw->canvas_config[i][0].phy_addr =
- decbuf_start;
+ decbuf_start;
hw->canvas_config[i][0].width =
- canvas_width;
+ canvas_width;
hw->canvas_config[i][0].height =
- canvas_height;
+ canvas_height;
hw->canvas_config[i][0].block_mode =
- CANVAS_BLKMODE_32X32;
+ hw->canvas_mode;
+ hw->canvas_config[i][0].endian =
+ (hw->canvas_mode == CANVAS_BLKMODE_LINEAR)?7:0;
canvas_config_config(canvas_y(canvas),
&hw->canvas_config[i][0]);
hw->canvas_config[i][1].phy_addr =
- decbuf_start + decbuf_y_size;
- hw->canvas_config[i][1].width =
- canvas_width;
- hw->canvas_config[i][1].height =
- canvas_height / 2;
- hw->canvas_config[i][1].block_mode =
- CANVAS_BLKMODE_32X32;
+ decbuf_start + decbuf_y_size;
+ hw->canvas_config[i][1].width = canvas_width;
+ hw->canvas_config[i][1].height = canvas_height / 2;
+ hw->canvas_config[i][1].block_mode = hw->canvas_mode;
+ hw->canvas_config[i][1].endian =
+ (hw->canvas_mode == CANVAS_BLKMODE_LINEAR)?7:0;
canvas_config_config(canvas_u(canvas),
- &hw->canvas_config[i][1]);
+ &hw->canvas_config[i][1]);
}
}
return;
@@ -1226,11 +1234,11 @@ static void vmpeg2_dump_state(struct vdec_s *vdec)
);
debug_print(DECODE_ID(hw), 0,
"is_framebase(%d), eos %d, state 0x%x, dec_result 0x%x dec_frm %d put_frm %d run %d not_run_ready %d,input_empty %d\n",
- input_frame_based(vdec),
+ vdec_frame_based(vdec),
hw->eos,
hw->stat,
hw->dec_result,
- hw->frame_num,
+ hw->dec_num,
hw->put_num,
hw->run_count,
hw->not_run_ready,
@@ -1239,7 +1247,8 @@ static void vmpeg2_dump_state(struct vdec_s *vdec)
for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) {
debug_print(DECODE_ID(hw), 0,
- "index %d, used %d\n", i, hw->vfbuf_use[i]);
+ "index %d, used %d, ref %d\n", i,
+ hw->vfbuf_use[i], hw->ref_use[i]);
}
if (vf_get_receiver(vdec->vf_provider_name)) {
@@ -1253,13 +1262,13 @@ static void vmpeg2_dump_state(struct vdec_s *vdec)
state);
}
debug_print(DECODE_ID(hw), 0,
- "%s, newq(%d/%d), dispq(%d/%d) vf peek/get/put (%d/%d/%d),drop=%d, buffer_not_ready %d\n",
+ "%s, newq(%d/%d), dispq(%d/%d) vf pre/get/put (%d/%d/%d),drop=%d, buffer_not_ready %d\n",
__func__,
kfifo_len(&hw->newframe_q),
VF_POOL_SIZE,
kfifo_len(&hw->display_q),
VF_POOL_SIZE,
- hw->peek_num,
+ hw->disp_num,
hw->get_num,
hw->put_num,
hw->drop_frame_count,
@@ -1283,7 +1292,7 @@ static void vmpeg2_dump_state(struct vdec_s *vdec)
debug_print(DECODE_ID(hw), 0,
"PARSER_VIDEO_WP=0x%x\n",
READ_PARSER_REG(PARSER_VIDEO_WP));
- if (input_frame_based(vdec) &&
+ if (vdec_frame_based(vdec) &&
debug_enable & PRINT_FRAMEBASE_DATA
) {
int jj;
@@ -1304,15 +1313,14 @@ static void vmpeg2_dump_state(struct vdec_s *vdec)
for (jj = 0; jj < hw->chunk->size; jj++) {
if ((jj & 0xf) == 0)
debug_print(DECODE_ID(hw),
- PRINT_FRAMEBASE_DATA,
+ PRINT_FRAMEBASE_DATA,
"%06x:", jj);
debug_print(DECODE_ID(hw),
PRINT_FRAMEBASE_DATA,
"%02x ", data[jj]);
if (((jj + 1) & 0xf) == 0)
debug_print(DECODE_ID(hw),
- PRINT_FRAMEBASE_DATA,
- "\n");
+ PRINT_FRAMEBASE_DATA, "\n");
}
if (!hw->chunk->block->is_mapped)
@@ -1333,18 +1341,19 @@ static void reset_process_time(struct vdec_mpeg12_hw_s *hw)
}
static void start_process_time(struct vdec_mpeg12_hw_s *hw)
{
- hw->decode_timeout_count = 2;
+ hw->decode_timeout_count = 10;
hw->start_process_time = jiffies;
}
static void timeout_process(struct vdec_mpeg12_hw_s *hw)
{
struct vdec_s *vdec = hw_to_vdec(hw);
+
+ reset_process_time(hw);
amvdec_stop();
debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR,
- "%s decoder timeout, status=%d, level=%d\n",
- __func__, vdec->status, READ_VREG(VLD_MEM_VIFIFO_LEVEL));
+ "%s decoder timeout, status=%d, level=%d\n",
+ __func__, vdec->status, READ_VREG(VLD_MEM_VIFIFO_LEVEL));
hw->dec_result = DEC_RESULT_DONE;
- reset_process_time(hw);
hw->first_i_frame_ready = 0;
vdec_schedule_work(&hw->work);
}
@@ -1365,9 +1374,7 @@ static void check_timer_func(unsigned long arg)
radr = 0;
}
- if (debug_enable == 0 &&
- (input_frame_based(vdec) ||
- (READ_VREG(VLD_MEM_VIFIFO_LEVEL) > 0x100)) &&
+ if (((debug_enable & PRINT_FLAG_TIMEOUT_STATUS) == 0) &&
(timeout_val > 0) &&
(hw->start_process_time > 0) &&
((1000 * (jiffies - hw->start_process_time) / HZ)
@@ -1393,20 +1400,32 @@ static void check_timer_func(unsigned long arg)
static int vmpeg12_hw_ctx_restore(struct vdec_mpeg12_hw_s *hw)
{
- u32 index;
+ u32 index, i;
index = find_buffer(hw);
if (index >= DECODE_BUFFER_NUM_MAX)
return -1;
- vmpeg12_canvas_init(hw);
+ if (!hw->init_flag)
+ vmpeg12_canvas_init(hw);
+ else {
+ WRITE_VREG(MREG_CO_MV_START, hw->buf_start);
+ for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) {
+ canvas_config_config(canvas_y(hw->canvas_spec[i]),
+ &hw->canvas_config[i][0]);
+ canvas_config_config(canvas_u(hw->canvas_spec[i]),
+ &hw->canvas_config[i][1]);
+ }
+ }
/* prepare REF0 & REF1
points to the past two IP buffers
prepare REC_CANVAS_ADDR and ANC2_CANVAS_ADDR
points to the output buffer*/
WRITE_VREG(MREG_REF0,
- (hw->refs[1] == -1) ? 0xffffffff : hw->canvas_spec[hw->refs[0]]);
+ (hw->refs[0] == -1) ? 0xffffffff :
+ hw->canvas_spec[hw->refs[0]]);
WRITE_VREG(MREG_REF1,
- (hw->refs[0] == -1) ? 0xffffffff : hw->canvas_spec[hw->refs[1]]);
+ (hw->refs[1] == -1) ? 0xffffffff :
+ hw->canvas_spec[hw->refs[1]]);
WRITE_VREG(REC_CANVAS_ADDR, hw->canvas_spec[index]);
WRITE_VREG(ANC2_CANVAS_ADDR, hw->canvas_spec[index]);
@@ -1432,6 +1451,8 @@ static int vmpeg12_hw_ctx_restore(struct vdec_mpeg12_hw_s *hw)
WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1);
/* clear buffer IN/OUT registers */
WRITE_VREG(MREG_BUFFEROUT, 0);
+ /* enable mailbox interrupt */
+ WRITE_VREG(ASSIST_MBOX1_MASK, 1);
/* set reference width and height */
if ((hw->frame_width != 0) && (hw->frame_height != 0))
WRITE_VREG(MREG_CMD,
@@ -1439,19 +1460,18 @@ static int vmpeg12_hw_ctx_restore(struct vdec_mpeg12_hw_s *hw)
else
WRITE_VREG(MREG_CMD, 0);
-
debug_print(DECODE_ID(hw), PRINT_FLAG_RESTORE,
- "0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n",
- hw->frame_width, hw->frame_height, hw->seqinfo,
- hw->reg_f_code_reg, hw->reg_slice_ver_pos_pic_type,
- hw->reg_mb_info);
+ "0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n",
+ hw->frame_width, hw->frame_height, hw->seqinfo,
+ hw->reg_f_code_reg, hw->reg_slice_ver_pos_pic_type,
+ hw->reg_mb_info);
WRITE_VREG(MREG_PIC_WIDTH, hw->reg_pic_width);
WRITE_VREG(MREG_PIC_HEIGHT, hw->reg_pic_height);
WRITE_VREG(MREG_SEQ_INFO, hw->seqinfo);
WRITE_VREG(F_CODE_REG, hw->reg_f_code_reg);
WRITE_VREG(SLICE_VER_POS_PIC_TYPE,
- hw->reg_slice_ver_pos_pic_type);
+ hw->reg_slice_ver_pos_pic_type);
WRITE_VREG(MB_INFO, hw->reg_mb_info);
WRITE_VREG(VCOP_CTRL_REG, hw->reg_vcop_ctrl_reg);
WRITE_VREG(AV_SCRATCH_H, hw->reg_signal_type);
@@ -1464,7 +1484,10 @@ static int vmpeg12_hw_ctx_restore(struct vdec_mpeg12_hw_s *hw)
#ifdef NV21
SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1<<17);
#endif
-
+ /*
+ if (!hw->ctx_valid)
+ WRITE_VREG(AV_SCRATCH_J, hw->userdata_wp_ctx);
+ */
if (hw->chunk) {
/*frame based input*/
WRITE_VREG(MREG_INPUT,
@@ -1490,8 +1513,10 @@ static void vmpeg12_local_init(struct vdec_mpeg12_hw_s *hw)
kfifo_put(&hw->newframe_q, (const struct vframe_s *)vf);
}
- for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++)
+ for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) {
hw->vfbuf_use[i] = 0;
+ hw->ref_use[i] = 0;
+ }
if (hw->mm_blk_handle) {
@@ -1505,7 +1530,8 @@ static void vmpeg12_local_init(struct vdec_mpeg12_hw_s *hw)
MAX_BMMU_BUFFER_NUM,
4 + PAGE_SHIFT,
CODEC_MM_FLAGS_CMA_CLEAR |
- CODEC_MM_FLAGS_FOR_VDECODER);
+ CODEC_MM_FLAGS_FOR_VDECODER |
+ hw->tvp_flag);
hw->eos = 0;
hw->frame_width = hw->frame_height = 0;
hw->frame_dur = hw->frame_prog = 0;
@@ -1515,7 +1541,8 @@ static void vmpeg12_local_init(struct vdec_mpeg12_hw_s *hw)
hw->dec_control &= DEC_CONTROL_INTERNAL_MASK;
hw->refs[0] = -1;
hw->refs[1] = -1;
- hw->frame_num = 0;
+ hw->disp_num = 0;
+ hw->dec_num = 0;
hw->put_num = 0;
hw->run_count = 0;
hw->not_run_ready = 0;
@@ -1525,6 +1552,7 @@ static void vmpeg12_local_init(struct vdec_mpeg12_hw_s *hw)
hw->drop_frame_count = 0;
hw->buffer_not_ready = 0;
hw->start_process_time = 0;
+ hw->init_flag = 0;
hw->error_frame_skip_level = error_frame_skip_level;
if (dec_control)
hw->dec_control = dec_control;
@@ -1557,7 +1585,6 @@ static s32 vmpeg12_init(struct vdec_mpeg12_hw_s *hw)
INIT_WORK(&hw->notify_work, vmpeg12_notify_work);
amvdec_enable();
-
init_timer(&hw->check_timer);
hw->check_timer.data = (unsigned long)hw;
hw->check_timer.function = check_timer_func;
@@ -1567,7 +1594,6 @@ static s32 vmpeg12_init(struct vdec_mpeg12_hw_s *hw)
hw->stat |= STAT_ISR_REG;
hw->buf_start = 0;
- hw->init_flag = 0;
WRITE_VREG(DECODE_STOP_POS, udebug_flag);
return 0;
@@ -1598,6 +1624,23 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
}
}
+#ifdef AGAIN_HAS_THRESHOLD
+ if (hw->next_again_flag&&
+ (!vdec_frame_based(vdec))) {
+ u32 parser_wr_ptr =
+ READ_PARSER_REG(PARSER_VIDEO_WP);
+ if (parser_wr_ptr >= hw->pre_parser_wr_ptr &&
+ (parser_wr_ptr - hw->pre_parser_wr_ptr) <
+ again_threshold) {
+ int r = vdec_sync_input(vdec);
+ debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW,
+ "%s buf level%x\n",
+ __func__, r);
+ return 0;
+ }
+ }
+#endif
+
index = find_buffer(hw);
if (index >= DECODE_BUFFER_NUM_MAX) {
hw->buffer_not_ready++;
@@ -1650,6 +1693,12 @@ void (*callback)(struct vdec_s *, void *),
hw->vdec_cb_arg = arg;
hw->vdec_cb = callback;
+#ifdef AGAIN_HAS_THRESHOLD
+ hw->pre_parser_wr_ptr =
+ READ_PARSER_REG(PARSER_VIDEO_WP);
+ hw->next_again_flag = 0;
+#endif
+
size = vdec_prepare_input(vdec, &hw->chunk);
if (size < 0) {
hw->input_empty++;
@@ -1657,9 +1706,15 @@ void (*callback)(struct vdec_s *, void *),
vdec_schedule_work(&hw->work);
return;
}
- if (input_frame_based(vdec)) {
+ if (vdec_frame_based(vdec) && debug_enable) {
u8 *data = NULL;
+
+ if (hw->chunk)
+ debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW,
+ "run: chunk offset 0x%x, size %d\n",
+ hw->chunk->offset, hw->chunk->size);
+
if (!hw->chunk->block->is_mapped)
data = codec_mm_vmap(hw->chunk->block->start +
hw->chunk->offset, size);
@@ -1711,15 +1766,7 @@ void (*callback)(struct vdec_s *, void *),
hw->input_empty = 0;
- debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW,
- "%s,%d, size=%d\n", __func__, __LINE__, size);
vdec_enable_input(vdec);
- hw->init_flag = 1;
-
- if (hw->chunk)
- debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW,
- "input chunk offset %d, size %d\n",
- hw->chunk->offset, hw->chunk->size);
hw->dec_result = DEC_RESULT_NONE;
if (vdec->mc_loaded) {
@@ -1753,6 +1800,7 @@ void (*callback)(struct vdec_s *, void *),
start_process_time(hw);
amvdec_start();
hw->stat |= STAT_VDEC_RUN;
+ hw->init_flag = 1;
mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL);
}
@@ -1773,8 +1821,7 @@ static int ammvdec_mpeg12_probe(struct platform_device *pdev)
return -EFAULT;
}
- hw = (struct vdec_mpeg12_hw_s *)devm_kzalloc(&pdev->dev,
- sizeof(struct vdec_mpeg12_hw_s), GFP_KERNEL);
+ hw = vzalloc(sizeof(struct vdec_mpeg12_hw_s));
if (hw == NULL) {
pr_info("\nammvdec_mpeg12 decoder driver alloc failed\n");
return -ENOMEM;
@@ -1805,18 +1852,30 @@ static int ammvdec_mpeg12_probe(struct platform_device *pdev)
&vf_provider_ops, pdata);
platform_set_drvdata(pdev, pdata);
-
+ hw->canvas_mode = CANVAS_BLKMODE_32X32;
hw->platform_dev = pdev;
+ hw->tvp_flag = vdec_secure(pdata) ? CODEC_MM_FLAGS_TVP : 0;
if (pdata->sys_info)
hw->vmpeg12_amstream_dec_info = *pdata->sys_info;
+ debug_print(DECODE_ID(hw), 0,
+ "%s, sysinfo: %dx%d, tvp_flag = 0x%x\n",
+ __func__,
+ hw->vmpeg12_amstream_dec_info.width,
+ hw->vmpeg12_amstream_dec_info.height,
+ hw->tvp_flag);
+
if (vmpeg12_init(hw) < 0) {
pr_info("ammvdec_mpeg12 init failed.\n");
- devm_kfree(&pdev->dev, (void *)hw);
+ if (hw) {
+ vfree(hw);
+ hw = NULL;
+ }
pdata->dec_status = NULL;
return -ENODEV;
}
+ vdec_set_prepare_level(pdata, start_decode_buf_level);
if (pdata->parallel_dec == 1)
vdec_core_request(pdata, CORE_MASK_VDEC_1);
else {
@@ -1852,8 +1911,9 @@ static int ammvdec_mpeg12_remove(struct platform_device *pdev)
hw->stat &= ~STAT_TIMER_ARM;
}
- cancel_work_sync(&hw->work);
+
cancel_work_sync(&hw->notify_work);
+ cancel_work_sync(&hw->work);
if (hw->mm_blk_handle) {
decoder_bmmu_box_free(hw->mm_blk_handle);
@@ -1876,7 +1936,10 @@ static int ammvdec_mpeg12_remove(struct platform_device *pdev)
vfree(hw->fw);
hw->fw = NULL;
}
-
+ if (hw) {
+ vfree(hw);
+ hw = NULL;
+ }
pr_info("ammvdec_mpeg12 removed.\n");
memset(&gvs, 0x0, sizeof(gvs));
@@ -1909,6 +1972,14 @@ static struct mconfig mmpeg12_configs[] = {
MC_PU32("dec_control", &dec_control),
MC_PU32("error_frame_skip_level", &error_frame_skip_level),
MC_PU32("decode_timeout_val", &decode_timeout_val),
+ MC_PU32("start_decode_buf_level", &start_decode_buf_level),
+ MC_PU32("pre_decode_buf_level", &pre_decode_buf_level),
+ MC_PU32("debug_enable", &debug_enable),
+ MC_PU32("udebug_flag", &udebug_flag),
+ MC_PU32("without_display_mode", &without_display_mode),
+#ifdef AGAIN_HAS_THRESHOLD
+ MC_PU32("again_threshold", &again_threshold),
+#endif
};
static struct mconfig_node mmpeg12_node;
@@ -1954,11 +2025,26 @@ MODULE_PARM_DESC(pre_decode_buf_level,
module_param(decode_timeout_val, uint, 0664);
MODULE_PARM_DESC(decode_timeout_val, "\n ammvdec_mpeg12 decode_timeout_val\n");
+
+module_param(start_decode_buf_level, int, 0664);
+MODULE_PARM_DESC(start_decode_buf_level,
+ "\n ammvdec_mpeg12 start_decode_buf_level\n");
+
module_param_array(max_process_time, uint, &max_decode_instance_num, 0664);
module_param(udebug_flag, uint, 0664);
MODULE_PARM_DESC(udebug_flag, "\n ammvdec_mpeg12 udebug_flag\n");
+
+#ifdef AGAIN_HAS_THRESHOLD
+module_param(again_threshold, uint, 0664);
+MODULE_PARM_DESC(again_threshold, "\n again_threshold\n");
+#endif
+
+module_param(without_display_mode, uint, 0664);
+MODULE_PARM_DESC(without_display_mode, "\n ammvdec_mpeg12 without_display_mode\n");
+
+
module_init(ammvdec_mpeg12_driver_init_module);
module_exit(ammvdec_mpeg12_driver_remove_module);
diff --git a/drivers/frame_provider/decoder/utils/amvdec.c b/drivers/frame_provider/decoder/utils/amvdec.c
index e4850b8..1d4e6f5 100644
--- a/drivers/frame_provider/decoder/utils/amvdec.c
+++ b/drivers/frame_provider/decoder/utils/amvdec.c
@@ -81,7 +81,7 @@ static void amvdec_pg_enable(bool enable)
} else {
AMVDEC_CLK_GATE_OFF(AMRISC);
- timeout = jiffies + HZ / 10;
+ timeout = jiffies + HZ / 100;
while (READ_VREG(MDEC_PIC_DC_STATUS) != 0) {
if (time_after(jiffies, timeout)) {
@@ -95,7 +95,7 @@ static void amvdec_pg_enable(bool enable)
}
AMVDEC_CLK_GATE_OFF(MDEC_CLK_PIC_DC);
- timeout = jiffies + HZ / 10;
+ timeout = jiffies + HZ / 100;
while (READ_VREG(DBLK_STATUS) & 1) {
if (time_after(jiffies, timeout)) {
@@ -108,7 +108,7 @@ static void amvdec_pg_enable(bool enable)
}
}
AMVDEC_CLK_GATE_OFF(MDEC_CLK_DBLK);
- timeout = jiffies + HZ / 10;
+ timeout = jiffies + HZ / 100;
while (READ_VREG(MC_STATUS0) & 1) {
if (time_after(jiffies, timeout)) {
@@ -121,7 +121,7 @@ static void amvdec_pg_enable(bool enable)
}
}
AMVDEC_CLK_GATE_OFF(MC_CLK);
- timeout = jiffies + HZ / 10;
+ timeout = jiffies + HZ / 100;
while (READ_VREG(DCAC_DMA_CTRL) & 0x8000) {
if (time_after(jiffies, timeout))
break;
@@ -810,7 +810,7 @@ EXPORT_SYMBOL(amhevc_start);
void amvdec_stop(void)
{
- ulong timeout = jiffies + HZ;
+ ulong timeout = jiffies + HZ/10;
WRITE_VREG(MPSR, 0);
WRITE_VREG(CPSR, 0);
@@ -820,7 +820,7 @@ void amvdec_stop(void)
break;
}
- timeout = jiffies + HZ;
+ timeout = jiffies + HZ/10;
while (READ_VREG(LMEM_DMA_CTRL) & 0x8000) {
if (time_after(jiffies, timeout))
break;
@@ -859,7 +859,7 @@ EXPORT_SYMBOL(amvdec_stop);
void amvdec2_stop(void)
{
if (has_vdec2()) {
- ulong timeout = jiffies + HZ;
+ ulong timeout = jiffies + HZ/10;
WRITE_VREG(VDEC2_MPSR, 0);
WRITE_VREG(VDEC2_CPSR, 0);
@@ -889,7 +889,7 @@ EXPORT_SYMBOL(amhcodec_stop);
void amhevc_stop(void)
{
if (has_hevc_vdec()) {
- ulong timeout = jiffies + HZ;
+ ulong timeout = jiffies + HZ/10;
WRITE_VREG(HEVC_MPSR, 0);
WRITE_VREG(HEVC_CPSR, 0);
@@ -899,7 +899,7 @@ void amhevc_stop(void)
break;
}
- timeout = jiffies + HZ;
+ timeout = jiffies + HZ/10;
while (READ_VREG(HEVC_LMEM_DMA_CTRL) & 0x8000) {
if (time_after(jiffies, timeout))
break;
diff --git a/firmware/video_ucode.bin b/firmware/video_ucode.bin
index 1ca3695..8c84166 100644
--- a/firmware/video_ucode.bin
+++ b/firmware/video_ucode.bin
@@ -1,5 +1,4 @@
-ѩ<K 7ƌ(?rH4؋!FR/a$f+쓚ї^8= w /ګUyTjI[cB)EKbaZU)S ٔ]h6-"EQF'ғ[1p2w3>Yyz#O-I"}kH2>4DE^UuCIq,]5]+F/+
-l8N]p_&KCAP
+Sա
B<
@@ -15683,26 +15682,26 @@ G
@
!
G
-
+

-
+
-
+
-:x
+:x
G @a
@x
-x
+@x


, 

-
+

-
+

!
@@ -15715,46 +15714,46 @@ J 
G$
`
-
+

@I
-
+
o
-I@Ip v Gv v Gw  p v Gv v Gw  
+I@Ip v Gv v Gw  p v Gv v Gw  
-
-
-k@W L
-
-
+
+
+k@W W
+
+
r
-H
-
+H
+
@I
 `

G `
-x
+x
 G`HR@
`"@
-
-
+
+
 b

2 x
-B 
- @
+B 
+ 


-
+

-
+
A
@a

-
+

@@ -15764,47 +15763,52 @@ G `
@I ^ G \ G Z 
-I
+I
-
-
+
+
I
-
+
QGbɑ@I2
QHbIb P PCII b
-
-Q RIc P PCII ?Hba  t
-
-\
+@
+Q RIc P PCII G  B 
+
+G LI B HbBx   a  t
+
+
+
+@^
GIǁ a
O
I@I

-
+
-
+@ x 
->G
-
-
+>
+@x
+ 
+
x QL FLBL
-@Lr@ǁ
+@Lr@ǁ
?I H
I HR
I  Ix  I  I  
L
H2X
- 
-
+ 
+
-
+
@@ -15823,9 +15827,9 @@ H2X

I
A@_`
-T@ GL
-U
-
+T@ GL @~ 
+U
+
A@
@@ -15861,7 +15865,7 @@ E===  E DL>L
b
D@ @
-
-@x HR& b@I"@J@Hb
+
+@x HR& b@I"@J@Hb
-
+