author | shihong.zheng <shihong.zheng@amlogic.com> | 2020-02-21 04:18:52 (GMT) |
---|---|---|
committer | Shen Liu <shen.liu@amlogic.com> | 2020-03-05 10:12:26 (GMT) |
commit | 64e9372b25ce5e713672bf478b6078fca08781a0 (patch) | |
tree | e5f32f627cfd1bc5b0eb13a539d1e40a567b83c9 | |
parent | c1df51d5a9edf5b6b75b4c309878dcd70364aad3 (diff) | |
download | media_modules-64e9372b25ce5e713672bf478b6078fca08781a0.zip media_modules-64e9372b25ce5e713672bf478b6078fca08781a0.tar.gz media_modules-64e9372b25ce5e713672bf478b6078fca08781a0.tar.bz2 |
mpeg4: fix mpeg4 cts fail. [1/1]
PD#SWPL-20956
Problem:
mpeg4 cts failed.
Solution:
update mpeg4 code from mainline.
gerrit: 76026 72410 72983 86773
91373 79602 and so on.
Verify:
x301
Change-Id: I7b7ef10c48270982829685d51f9b1a285ef3a76b
Signed-off-by: shihong.zheng <shihong.zheng@amlogic.com>
-rw-r--r-- | drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c | 1217 |
1 files changed, 726 insertions, 491 deletions
diff --git a/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c b/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c index 406ae8b..8d512d5 100644 --- a/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c +++ b/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c @@ -60,6 +60,7 @@ #define I_PICTURE 0 #define P_PICTURE 1 #define B_PICTURE 2 +#define GET_PIC_TYPE(type) ("IPB####"[type&0x3]) #define ORI_BUFFER_START_ADDR 0x01000000 #define DEFAULT_MEM_SIZE (32*SZ_1M) @@ -93,7 +94,7 @@ #define PARC_EXTENDED 15 #define VF_POOL_SIZE 16 -#define DECODE_BUFFER_NUM_MAX 4 +#define DECODE_BUFFER_NUM_MAX 8 #define PUT_INTERVAL (HZ/100) #define MAX_BMMU_BUFFER_NUM (DECODE_BUFFER_NUM_MAX + 1) #define WORKSPACE_SIZE (12*SZ_64K) @@ -112,12 +113,19 @@ static u32 buf_size = 32 * 1024 * 1024; #define DUR2PTS(x) ((x) - ((x) >> 4)) +/* 96000/(60fps* 2field) = 800, 96000/10fps = 9600 */ +#define MPEG4_VALID_DUR(x) ((x < 9600) && (x > 799)) + +#define MAX_MPEG4_SUPPORT_SIZE (1920*1088) + #define DEC_RESULT_NONE 0 #define DEC_RESULT_DONE 1 #define DEC_RESULT_AGAIN 2 #define DEC_RESULT_ERROR 3 #define DEC_RESULT_FORCE_EXIT 4 -#define DEC_RESULT_EOS 5 +#define DEC_RESULT_EOS 5 +#define DEC_RESULT_UNFINISH 6 + #define DEC_DECODE_TIMEOUT 0x21 #define DECODE_ID(hw) (hw_to_vdec(hw)->id) #define DECODE_STOP_POS AV_SCRATCH_K @@ -129,15 +137,18 @@ 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); static int pre_decode_buf_level = 0x800; +static int start_decode_buf_level = 0x4000; static int debug_enable; static unsigned int radr; static unsigned int rval; +static unsigned int frmbase_cont_bitlevel = 0x40; #define VMPEG4_DEV_NUM 9 static unsigned int max_decode_instance_num = VMPEG4_DEV_NUM; static unsigned int max_process_time[VMPEG4_DEV_NUM]; -static unsigned int decode_timeout_val = 100; +static unsigned int decode_timeout_val = 200; +static u32 without_display_mode; #undef pr_info #define pr_info printk @@ -175,6 +186,17 @@ int mmpeg4_debug_print(int index, int debug_flag, const char *fmt, ...) return 0; } +struct pic_info_t { + int index; + u32 pic_type; + u32 pic_info; + u32 pts; + u64 pts64; + bool pts_valid; + u32 duration; + u32 repeat_cnt; +}; + struct vdec_mpeg4_hw_s { spinlock_t lock; struct platform_device *platform_dev; @@ -204,13 +226,18 @@ struct vdec_mpeg4_hw_s { u32 reg_rv_ai_mb_count; struct timer_list check_timer; u32 decode_timeout_count; - u32 start_process_time; + u32 timeout_cnt; + unsigned long int start_process_time; + u32 last_vld_level; u8 init_flag; u32 eos; void *mm_blk_handle; struct vframe_chunk_s *chunk; + u32 chunk_offset; + u32 chunk_size; + u32 chunk_frame_count; u32 stat; unsigned long buf_start; u32 buf_size; @@ -230,15 +257,13 @@ struct vdec_mpeg4_hw_s { u32 frame_num_since_last_anch; u64 last_anch_pts_us64; + u32 last_pts; + u64 last_pts64; u32 pts_hit; u32 pts_missed; u32 pts_i_hit; u32 pts_i_missed; - u32 decoded_type[DECODE_BUFFER_NUM_MAX]; - 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 pic[DECODE_BUFFER_NUM_MAX]; u32 canvas_spec[DECODE_BUFFER_NUM_MAX]; #ifdef NV21 struct canvas_config_s canvas_config[DECODE_BUFFER_NUM_MAX][2]; @@ -264,12 +289,17 @@ struct vdec_mpeg4_hw_s { u32 get_num; u32 first_i_frame_ready; u32 drop_frame_count; - u32 timeout_flag; + u32 unstable_pts; + u32 last_dec_pts; struct firmware_s *fw; + u32 blkmode; + wait_queue_head_t wait_q; }; static void vmpeg4_local_init(struct vdec_mpeg4_hw_s *hw); static int vmpeg4_hw_ctx_restore(struct vdec_mpeg4_hw_s *hw); +static unsigned char + get_data_check_sum(struct vdec_mpeg4_hw_s *hw, int size); #define PROVIDER_NAME "vdec.mpeg4" @@ -347,15 +377,15 @@ static void set_frame_info(struct vdec_mpeg4_hw_s *hw, struct vframe_s *vf, /* always stretch to 16:9 */ } else if (pixel_ratio > 0x0f) { num = (pixel_ratio >> 8) * - hw->vmpeg4_amstream_dec_info.width * num; + hw->frame_width * num; ar = div_u64((pixel_ratio & 0xff) * - hw->vmpeg4_amstream_dec_info.height * den * 0x100ULL + + hw->frame_height * den * 0x100ULL + (num >> 1), num); } else { switch (aspect_ratio_table[pixel_ratio]) { case 0: - num = hw->vmpeg4_amstream_dec_info.width * num; - ar = (hw->vmpeg4_amstream_dec_info.height * den * + num = hw->frame_width * num; + ar = (hw->frame_height * den * 0x100 + (num >> 1)) / num; break; case 1: @@ -427,17 +457,266 @@ static inline void vmpeg4_save_hw_context(struct vdec_mpeg4_hw_s *hw) hw->reg_rv_ai_mb_count = READ_VREG(RV_AI_MB_COUNT); } +static int update_ref(struct vdec_mpeg4_hw_s *hw, int index) +{ + hw->vfbuf_use[index]++; + + if (hw->refs[1] == -1) { + hw->refs[1] = index; + index = -1; + } 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]; + } + + return index; +} + + +static int prepare_display_buf(struct vdec_mpeg4_hw_s * hw, + struct pic_info_t *pic) +{ + struct vframe_s *vf = NULL; + struct vdec_s *vdec = hw_to_vdec(hw); + int index = pic->index; + + if (pic->pic_info & INTERLACE_FLAG) { + if (kfifo_get(&hw->newframe_q, &vf) == 0) { + mmpeg4_debug_print(DECODE_ID(hw), 0, + "fatal error, no available buffer slot."); + return -1; + } + + vf->index = pic->index; + vf->width = hw->frame_width; + vf->height = hw->frame_height; + vf->bufWidth = 1920; + vf->flag = 0; + vf->orientation = hw->vmpeg4_rotation; + vf->pts = pic->pts; + vf->pts_us64 = pic->pts64; + vf->duration = pic->duration >> 1; + vf->duration_pulldown = 0; + vf->type = (pic->pic_info & TOP_FIELD_FIRST_FLAG) ? + VIDTYPE_INTERLACE_TOP : VIDTYPE_INTERLACE_BOTTOM; +#ifdef NV21 + vf->type |= VIDTYPE_VIU_NV21; +#endif + set_frame_info(hw, vf, pic->index); + + hw->vfbuf_use[pic->index]++; + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, + "field0: pts %d, pts64 %lld, w %d, h %d, dur %d\n", + vf->pts, vf->pts_us64, vf->width, vf->height, vf->duration); + + if ((hw->first_i_frame_ready == 0) + && (pic->pic_type != I_PICTURE)) { + hw->drop_frame_count++; + hw->vfbuf_use[index]--; + kfifo_put(&hw->newframe_q, + (const struct vframe_s *)vf); + return 0; + } else { + vf->mem_handle = + decoder_bmmu_box_get_mem_handle( + hw->mm_blk_handle, index); + kfifo_put(&hw->display_q, + (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); + hw->frame_num++; + 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); + } + + if (kfifo_get(&hw->newframe_q, &vf) == 0) { + mmpeg4_debug_print(DECODE_ID(hw), 0, + "error, no available buf.\n"); + hw->dec_result = DEC_RESULT_ERROR; + return -1; + } + + vf->index = pic->index; + vf->width = hw->frame_width; + vf->height = hw->frame_height; + vf->bufWidth = 1920; + vf->flag = 0; + vf->orientation = hw->vmpeg4_rotation; + vf->pts = 0; + vf->pts_us64 = 0; + vf->duration = pic->duration >> 1; + vf->duration_pulldown = 0; + vf->type = (pic->pic_info & TOP_FIELD_FIRST_FLAG) ? + VIDTYPE_INTERLACE_BOTTOM : VIDTYPE_INTERLACE_TOP; +#ifdef NV21 + vf->type |= VIDTYPE_VIU_NV21; +#endif + set_frame_info(hw, vf, pic->index); + + hw->vfbuf_use[pic->index]++; + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, + "filed1: pts %d, pts64 %lld, w %d, h %d, dur: %d\n", + vf->pts, vf->pts_us64, vf->width, vf->height, vf->duration); + if ((hw->first_i_frame_ready == 0) && + (pic->pic_type != I_PICTURE)) { + hw->drop_frame_count++; + hw->vfbuf_use[index]--; + kfifo_put(&hw->newframe_q, + (const struct vframe_s *)vf); + } else { + vf->mem_handle = + decoder_bmmu_box_get_mem_handle( + hw->mm_blk_handle, index); + kfifo_put(&hw->display_q, + (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); + + hw->frame_num++; + 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); + } + } else { + /* progressive */ + if (kfifo_get(&hw->newframe_q, &vf) == 0) { + mmpeg4_debug_print(DECODE_ID(hw), 0, + "error, no available buf\n"); + hw->dec_result = DEC_RESULT_ERROR; + return -1; + } + + vf->index = index; + vf->width = hw->frame_width; + vf->height = hw->frame_height; + vf->bufWidth = 1920; + vf->flag = 0; + vf->orientation = hw->vmpeg4_rotation; + vf->pts = pic->pts; + vf->pts_us64 = pic->pts64; + vf->duration = pic->duration; + vf->duration_pulldown = pic->repeat_cnt * + pic->duration; +#ifdef NV21 + vf->type = VIDTYPE_PROGRESSIVE | + VIDTYPE_VIU_FIELD | VIDTYPE_VIU_NV21; +#else + vf->type = VIDTYPE_PROGRESSIVE | + VIDTYPE_VIU_FIELD; +#endif + set_frame_info(hw, vf, index); + + hw->vfbuf_use[index]++; + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, + "prog: pts %d, pts64 %lld, w %d, h %d, dur %d\n", + vf->pts, vf->pts_us64, vf->width, vf->height, vf->duration); + + if ((hw->first_i_frame_ready == 0) && + (pic->pic_type != I_PICTURE)) { + hw->drop_frame_count++; + hw->vfbuf_use[index]--; + kfifo_put(&hw->newframe_q, + (const struct vframe_s *)vf); + } else { + vf->mem_handle = + decoder_bmmu_box_get_mem_handle( + hw->mm_blk_handle, index); + kfifo_put(&hw->display_q, + (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); + + hw->frame_num++; + 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 vmpeg4_prepare_input(struct vdec_mpeg4_hw_s *hw) +{ + struct vdec_s *vdec = hw_to_vdec(hw); + struct vdec_input_s *input = &vdec->input; + struct vframe_block_list_s *block = NULL; + struct vframe_chunk_s *chunk = hw->chunk; + int dummy; + + if (chunk == NULL) + return; + + /* full reset to HW input */ + WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 0); + + /* reset VLD fifo for all vdec */ + WRITE_VREG(DOS_SW_RESET0, (1<<5) | (1<<4) | (1<<3)); + WRITE_VREG(DOS_SW_RESET0, 0); + + dummy = READ_RESET_REG(RESET0_REGISTER); + WRITE_VREG(POWER_CTL_VLD, 1 << 4); + + /* + *setup HW decoder input buffer (VLD context) + * based on input->type and input->target + */ + if (input_frame_based(input)) { + block = chunk->block; + + WRITE_VREG(VLD_MEM_VIFIFO_START_PTR, block->start); + WRITE_VREG(VLD_MEM_VIFIFO_END_PTR, block->start + + block->size - 8); + WRITE_VREG(VLD_MEM_VIFIFO_CURR_PTR, + round_down(block->start + hw->chunk_offset, + VDEC_FIFO_ALIGN)); + + WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 1); + WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 0); + + /* set to manual mode */ + WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, 2); + WRITE_VREG(VLD_MEM_VIFIFO_RP, + round_down(block->start + hw->chunk_offset, + VDEC_FIFO_ALIGN)); + dummy = hw->chunk_offset + hw->chunk_size + + VLD_PADDING_SIZE; + if (dummy >= block->size) + dummy -= block->size; + WRITE_VREG(VLD_MEM_VIFIFO_WP, + round_down(block->start + dummy, + VDEC_FIFO_ALIGN)); + + WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, 3); + WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, 2); + + WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, + (0x11 << 16) | (1<<10) | (7<<3)); + + } +} + static irqreturn_t vmpeg4_isr_thread_fn(struct vdec_s *vdec, int irq) { u32 reg; - struct vframe_s *vf = NULL; u32 picture_type; int index; u32 pts, offset = 0; - bool pts_valid = false; u64 pts_us64 = 0; + u32 dec_w, dec_h; u32 time_increment_resolution, fixed_vop_rate, vop_time_inc; u32 repeat_cnt, duration = 3200; + struct pic_info_t *dec_pic, *disp_pic; struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)(vdec->private); if (hw->eos) return IRQ_HANDLED; @@ -460,21 +739,23 @@ static irqreturn_t vmpeg4_isr_thread_fn(struct vdec_s *vdec, int irq) time_increment_resolution = READ_VREG(MP4_RATE); fixed_vop_rate = time_increment_resolution >> 16; time_increment_resolution &= 0xffff; - if (time_increment_resolution > 0 && fixed_vop_rate == 0) + if (time_increment_resolution > 0 && + fixed_vop_rate == 0) hw->sys_mp4_rate = time_increment_resolution; + if (hw->vmpeg4_amstream_dec_info.rate == 0) { - if ((fixed_vop_rate != 0) && (time_increment_resolution != 0)) { - /* fixed VOP rate */ + if ((fixed_vop_rate != 0) && + (time_increment_resolution != 0)) { hw->vmpeg4_amstream_dec_info.rate = fixed_vop_rate * DURATION_UNIT / time_increment_resolution; } else if (time_increment_resolution == 0 - && hw->sys_mp4_rate > 0) + && hw->sys_mp4_rate > 0) time_increment_resolution = hw->sys_mp4_rate; } mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, - "resolution=%d,fvop=%d,rate=%d\n", - time_increment_resolution, fixed_vop_rate, - hw->vmpeg4_amstream_dec_info.rate); + "time_inc_res = %d, fixed_vop_rate = %d, rate = %d\n", + time_increment_resolution, fixed_vop_rate, + hw->vmpeg4_amstream_dec_info.rate); if (reg == 2) { /* timeout when decoding next frame */ @@ -483,20 +764,22 @@ static irqreturn_t vmpeg4_isr_thread_fn(struct vdec_s *vdec, int irq) * at the beginning when only VOL head is available save * HW context also, such as for the QTable from VCOP register */ - mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_VLD_DETAIL, - "ammvdec_mpeg4: timeout\n"); - mmpeg4_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)) { + mmpeg4_debug_print(DECODE_ID(hw), + PRINT_FLAG_VLD_DETAIL, + "%s, level = %x, vfifo_ctrl = %x, bitcnt = %d\n", + __func__, + READ_VREG(VLD_MEM_VIFIFO_LEVEL), + READ_VREG(VLD_MEM_VIFIFO_CONTROL), + READ_VREG(VIFF_BIT_CNT)); + + if (vdec_frame_based(vdec)) { vmpeg4_save_hw_context(hw); - hw->timeout_flag++; + hw->dec_result = DEC_RESULT_DONE; + vdec_schedule_work(&hw->work); } else { - hw->dec_result = DEC_RESULT_AGAIN; - - schedule_work(&hw->work); + reset_process_time(hw); + hw->dec_result = DEC_RESULT_AGAIN; + vdec_schedule_work(&hw->work); } return IRQ_HANDLED; } else { @@ -506,31 +789,29 @@ static irqreturn_t vmpeg4_isr_thread_fn(struct vdec_s *vdec, int irq) vop_time_inc = READ_VREG(MP4_VOP_TIME_INC); index = spec_to_index(hw, READ_VREG(REC_CANVAS_ADDR)); - if (index < 0) { mmpeg4_debug_print(DECODE_ID(hw), 0, - "invalid buffer index."); + "invalid buffer index %d. rec = %x\n", + index, READ_VREG(REC_CANVAS_ADDR)); hw->dec_result = DEC_RESULT_ERROR; - - schedule_work(&hw->work); - + vdec_schedule_work(&hw->work); return IRQ_HANDLED; } - mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_BUFFER_DETAIL, - "index=%d, used=%d cnt=%d, vopinc=%d\n", - index, hw->vfbuf_use[index], repeat_cnt, vop_time_inc); - hw->dec_result = DEC_RESULT_DONE; + dec_pic = &hw->pic[index]; + dec_pic->pts_valid = false; + dec_pic->pts = 0; + dec_pic->pts64 = 0; + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_BUFFER_DETAIL, + "new pic: index=%d, used=%d, repeat=%d, time_inc=%d\n", + index, hw->vfbuf_use[index], repeat_cnt, vop_time_inc); - if (hw->vmpeg4_amstream_dec_info.width == 0) { - hw->vmpeg4_amstream_dec_info.width = - READ_VREG(MP4_PIC_WH) >> 16; - } - - if (hw->vmpeg4_amstream_dec_info.height == 0) { - hw->vmpeg4_amstream_dec_info.height = - READ_VREG(MP4_PIC_WH) & 0xffff; - } + dec_w = READ_VREG(MP4_PIC_WH)>> 16; + dec_h = READ_VREG(MP4_PIC_WH) & 0xffff; + if (dec_w != 0) + hw->frame_width = dec_w; + if (dec_h != 0) + hw->frame_height = dec_h; if (hw->vmpeg4_amstream_dec_info.rate == 0) { if (vop_time_inc < hw->last_vop_time_inc) { @@ -547,15 +828,20 @@ static irqreturn_t vmpeg4_isr_thread_fn(struct vdec_s *vdec, int irq) if ((hw->rate_detect >= RATE_DETECT_COUNT) && (time_increment_resolution != 0)) { hw->vmpeg4_amstream_dec_info.rate = - duration * DURATION_UNIT / - time_increment_resolution; + duration * DURATION_UNIT / + time_increment_resolution; duration = - hw->vmpeg4_amstream_dec_info.rate; + hw->vmpeg4_amstream_dec_info.rate; } } else { hw->rate_detect = 0; hw->last_duration = duration; } + if (MPEG4_VALID_DUR(duration)) { + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, + "warn: duration %x, set 0\n", duration); + duration = 0; + } } else { duration = hw->vmpeg4_amstream_dec_info.rate; #if 0 @@ -565,103 +851,89 @@ static irqreturn_t vmpeg4_isr_thread_fn(struct vdec_s *vdec, int irq) #endif } - if ((I_PICTURE == picture_type) || + /* frame mode with unstable pts */ + if (hw->unstable_pts && hw->chunk) { + dec_pic->pts_valid = hw->chunk->pts_valid; + dec_pic->pts = hw->chunk->pts; + dec_pic->pts64 = hw->chunk->pts64; + if ((B_PICTURE == picture_type) || + (hw->last_dec_pts == dec_pic->pts)) + dec_pic->pts_valid = 0; + + hw->last_dec_pts = dec_pic->pts; + } else if ((I_PICTURE == picture_type) || (P_PICTURE == picture_type)) { offset = READ_VREG(MP4_OFFSET_REG); if (hw->chunk) { - hw->pts_valid[index] = hw->chunk->pts_valid; - hw->pts[index] = hw->chunk->pts; - hw->pts64[index] = hw->chunk->pts64; + dec_pic->pts_valid = hw->chunk->pts_valid; + dec_pic->pts = hw->chunk->pts; + dec_pic->pts64 = hw->chunk->pts64; } else { - if (pts_lookup_offset_us64 - (PTS_TYPE_VIDEO, offset, &pts, 3000, - &pts_us64) == 0) { - hw->pts_valid[index] = true; - hw->pts[index] = pts; - hw->pts64[index] = pts_us64; + if (pts_lookup_offset_us64(PTS_TYPE_VIDEO, offset, + &pts, 3000, &pts_us64) == 0) { + dec_pic->pts_valid = true; + dec_pic->pts = pts; + dec_pic->pts64 = pts_us64; hw->pts_hit++; } else { - hw->pts_valid[index] = false; + dec_pic->pts_valid = false; hw->pts_missed++; } } mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, - "I/P offset 0x%x, pts_valid %d pts=0x%x,index=%d,used=%d\n", - offset, hw->pts_valid[index], - hw->pts[index], index, hw->vfbuf_use[index]); - } else { - hw->pts_valid[index] = false; - hw->pts[index] = 0; - hw->pts64[index] = 0; + "%c, offset=0x%x, pts=0x%x(%d), index=%d, used=%d\n", + GET_PIC_TYPE(picture_type), offset, dec_pic->pts, + dec_pic->pts_valid, index, hw->vfbuf_use[index]); } - hw->buffer_info[index] = reg; + dec_pic->index = index; + dec_pic->pic_info = reg; + dec_pic->pic_type = picture_type; + dec_pic->duration = duration; hw->vfbuf_use[index] = 0; - hw->decoded_type[index] = picture_type; mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW, - "amvdec_mpeg4: decoded buffer %d, frame_type %s,pts=%x\n", - index, - (picture_type == I_PICTURE) ? "I" : - (picture_type == P_PICTURE) ? "P" : "B", - hw->pts[index]); - - /* Buffer management - * todo: add sequence-end flush - */ + "mmpeg4: pic_num: %d, index %d, type %c, pts %x\n", + hw->frame_num, index, + GET_PIC_TYPE(picture_type), + dec_pic->pts); + + /* buffer management */ if ((picture_type == I_PICTURE) || (picture_type == P_PICTURE)) { - hw->vfbuf_use[index]++; - - if (hw->refs[1] == -1) { - hw->refs[1] = index; - index = -1; - } 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_ref(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 or disp immediately. + * depend on if there are two ref frames */ if (hw->refs[1] == -1) index = -1; } - vmpeg4_save_hw_context(hw); - if (index < 0) { - schedule_work(&hw->work); + vdec_schedule_work(&hw->work); return IRQ_HANDLED; } - - reg = hw->buffer_info[index]; - pts_valid = hw->pts_valid[index]; - pts = hw->pts[index]; - pts_us64 = hw->pts64[index]; + disp_pic = &hw->pic[index]; if ((hw->first_i_frame_ready == 0) && - (I_PICTURE == hw->decoded_type[index])) + (I_PICTURE == disp_pic->pic_type)) hw->first_i_frame_ready = 1; - mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, - "queued %d, pts = 0x%x, pts_valid=%d,index=%d,used=%d,type=%d,decode_type=%d\n", - index, pts, pts_valid, index, hw->vfbuf_use[index], - picture_type, hw->decoded_type[index]); - if (pts_valid) { - hw->last_anch_pts = pts; - hw->last_anch_pts_us64 = pts_us64; + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW, + "disp: index=%d, pts=%x(%d), used=%d, picout=%c(dec=%c)\n", + index, disp_pic->pts, disp_pic->pts_valid, + hw->vfbuf_use[index], + GET_PIC_TYPE(disp_pic->pic_type), + GET_PIC_TYPE(picture_type)); + + if (disp_pic->pts_valid) { + hw->last_anch_pts = disp_pic->pts; + hw->last_anch_pts_us64 = disp_pic->pts64; hw->frame_num_since_last_anch = 0; hw->vop_time_inc_since_last_anch = 0; - } else if (input_stream_based(vdec)) { - pts = hw->last_anch_pts; - pts_us64 = hw->last_anch_pts_us64; + } else if (vdec_stream_based(vdec)) { + disp_pic->pts = hw->last_anch_pts; + disp_pic->pts64 = hw->last_anch_pts_us64; if ((time_increment_resolution != 0) && (fixed_vop_rate == 0) && @@ -682,230 +954,153 @@ static irqreturn_t vmpeg4_isr_thread_fn(struct vdec_s *vdec, int irq) hw->vop_time_inc_since_last_anch += duration; - pts += hw->vop_time_inc_since_last_anch * + disp_pic->pts += hw->vop_time_inc_since_last_anch * PTS_UNIT / time_increment_resolution; - pts_us64 += (hw->vop_time_inc_since_last_anch * + disp_pic->pts64 += (hw->vop_time_inc_since_last_anch * PTS_UNIT / time_increment_resolution) * 100 / 9; if (hw->vop_time_inc_since_last_anch > (1 << 14)) { /* avoid overflow */ - hw->last_anch_pts = pts; - hw->last_anch_pts_us64 = pts_us64; + hw->last_anch_pts = disp_pic->pts; + hw->last_anch_pts_us64 = disp_pic->pts64; hw->vop_time_inc_since_last_anch = 0; } } else { /* fixed VOP rate */ hw->frame_num_since_last_anch++; - pts += DUR2PTS(hw->frame_num_since_last_anch * + disp_pic->pts += DUR2PTS(hw->frame_num_since_last_anch * hw->vmpeg4_amstream_dec_info.rate); - pts_us64 += DUR2PTS( + disp_pic->pts64 += DUR2PTS( hw->frame_num_since_last_anch * - hw->vmpeg4_amstream_dec_info.rate) * - 100 / 9; + hw->vmpeg4_amstream_dec_info.rate) * 100 / 9; if (hw->frame_num_since_last_anch > (1 << 15)) { /* avoid overflow */ - hw->last_anch_pts = pts; - hw->last_anch_pts_us64 = pts_us64; + hw->last_anch_pts = disp_pic->pts; + hw->last_anch_pts_us64 = disp_pic->pts64; hw->frame_num_since_last_anch = 0; } } + } else if (hw->unstable_pts && hw->chunk && + MPEG4_VALID_DUR(duration)) { + /* invalid pts calc */ + hw->frame_num_since_last_anch = hw->chunk_frame_count; + disp_pic->pts = hw->last_anch_pts + + DUR2PTS(hw->frame_num_since_last_anch * + duration); + disp_pic->pts64 = hw->last_anch_pts_us64 + + DUR2PTS(hw->frame_num_since_last_anch * + duration) * 100 / 9; + + if (hw->frame_num_since_last_anch > (1 << 15)) { + /* avoid overflow */ + hw->last_anch_pts = disp_pic->pts; + hw->last_anch_pts_us64 = disp_pic->pts64; + hw->frame_num_since_last_anch = 0; + } else + disp_pic->pts_valid = 1; } - if (reg & INTERLACE_FLAG) { /* interlace */ - if (kfifo_get(&hw->newframe_q, &vf) == 0) { - mmpeg4_debug_print(DECODE_ID(hw), 0, - "fatal error, no available buffer slot."); - return IRQ_HANDLED; - } + if (vdec_frame_based(vdec) && + (hw->unstable_pts) && + MPEG4_VALID_DUR(duration)) { - vf->index = index; - vf->width = hw->vmpeg4_amstream_dec_info.width; - vf->height = hw->vmpeg4_amstream_dec_info.height; - vf->bufWidth = 1920; - vf->flag = 0; - vf->orientation = hw->vmpeg4_rotation; - vf->pts = pts; - vf->pts_us64 = pts_us64; - vf->duration = duration >> 1; - vf->duration_pulldown = 0; - vf->type = (reg & TOP_FIELD_FIRST_FLAG) ? - VIDTYPE_INTERLACE_TOP : - VIDTYPE_INTERLACE_BOTTOM; -#ifdef NV21 - vf->type |= VIDTYPE_VIU_NV21; -#endif - set_frame_info(hw, vf, index); + u32 threshold = DUR2PTS(duration) >> 3; - hw->vfbuf_use[index]++; - mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, - "pts0=%d,pts64=%lld,w%d,h%d,dur:%d\n", - vf->pts, vf->pts_us64, - vf->width, vf->height, - vf->duration); - if ((hw->first_i_frame_ready == 0) - && (picture_type != I_PICTURE)) { - hw->drop_frame_count++; - hw->vfbuf_use[index]--; - - kfifo_put(&hw->newframe_q, - (const struct vframe_s *)vf); - } else { - kfifo_put(&hw->display_q, - (const struct vframe_s *)vf); - ATRACE_COUNTER(MODULE_NAME, vf->pts); - hw->frame_num++; - vf_notify_receiver(vdec->vf_provider_name, - VFRAME_EVENT_PROVIDER_VFRAME_READY, - NULL); + if (disp_pic->pts <= (hw->last_pts + threshold)) { + disp_pic->pts = hw->last_pts + DUR2PTS(duration); + disp_pic->pts64 = hw->last_pts64 + + (DUR2PTS(duration)*100/9); } - if (kfifo_get(&hw->newframe_q, &vf) == 0) { - mmpeg4_debug_print(DECODE_ID(hw), 0, - "fatal error, no available buffer slot."); - hw->dec_result = DEC_RESULT_ERROR; - schedule_work(&hw->work); - return IRQ_HANDLED; - } - - vf->index = index; - vf->width = hw->vmpeg4_amstream_dec_info.width; - vf->height = hw->vmpeg4_amstream_dec_info.height; - vf->bufWidth = 1920; - vf->flag = 0; - vf->orientation = hw->vmpeg4_rotation; - - vf->pts = 0; - vf->pts_us64 = 0; - vf->duration = duration >> 1; - - vf->duration_pulldown = 0; - vf->type = (reg & TOP_FIELD_FIRST_FLAG) ? - VIDTYPE_INTERLACE_BOTTOM : VIDTYPE_INTERLACE_TOP; -#ifdef NV21 - vf->type |= VIDTYPE_VIU_NV21; -#endif - set_frame_info(hw, vf, index); - - hw->vfbuf_use[index]++; - mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, - "pts1=%d,pts64=%lld,w%d,h%d,dur:%d\n", - vf->pts, vf->pts_us64, - vf->width, vf->height, - vf->duration); - if ((hw->first_i_frame_ready == 0) - && (picture_type != I_PICTURE)) { - hw->drop_frame_count++; - hw->vfbuf_use[index]--; - - kfifo_put(&hw->newframe_q, - (const struct vframe_s *)vf); - } else { - kfifo_put(&hw->display_q, - (const struct vframe_s *)vf); - ATRACE_COUNTER(MODULE_NAME, vf->pts); - hw->frame_num++; - vf_notify_receiver(vdec->vf_provider_name, - VFRAME_EVENT_PROVIDER_VFRAME_READY, - NULL); - } - } else { /* progressive */ - if (kfifo_get(&hw->newframe_q, &vf) == 0) { - mmpeg4_debug_print(DECODE_ID(hw), 0, - "fatal error, no available buffer slot."); - return IRQ_HANDLED; - } - - vf->index = index; - vf->width = hw->vmpeg4_amstream_dec_info.width; - vf->height = hw->vmpeg4_amstream_dec_info.height; - vf->bufWidth = 1920; - vf->flag = 0; - vf->orientation = hw->vmpeg4_rotation; - vf->pts = pts; - vf->pts_us64 = pts_us64; - vf->duration = duration; - vf->duration_pulldown = repeat_cnt * duration; -#ifdef NV21 - vf->type = - VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD | - VIDTYPE_VIU_NV21; -#else - vf->type = - VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; -#endif - set_frame_info(hw, vf, index); - - hw->vfbuf_use[index]++; - mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, - "pts=%d,pts64=%lld,w%d,h%d,index=%d,used=%d,dur:%d, flag=%d, type=%d\n", - vf->pts, vf->pts_us64, - vf->width, vf->height, - index, hw->vfbuf_use[index], - vf->duration, - hw->timeout_flag, picture_type); - if ((hw->first_i_frame_ready == 0) - && (picture_type != I_PICTURE)) { - hw->drop_frame_count++; - hw->vfbuf_use[index]--; - hw->timeout_flag++; - kfifo_put(&hw->newframe_q, - (const struct vframe_s *)vf); - } else { - if (hw->timeout_flag > 2) - hw->timeout_flag = 2; - if (hw->timeout_flag && input_frame_based(vdec)) - vf->duration = duration * (hw->timeout_flag + 1); - kfifo_put(&hw->display_q, - (const struct vframe_s *)vf); - ATRACE_COUNTER(MODULE_NAME, vf->pts); - hw->frame_num++; - hw->timeout_flag = 0; - vf_notify_receiver(vdec->vf_provider_name, - VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + if (!disp_pic->pts_valid) { + disp_pic->pts = 0; + disp_pic->pts64 = 0; } } + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, + "disp: pic_type %c, pts %d(%lld), diff %d, cnt %d\n", + GET_PIC_TYPE(disp_pic->pic_type), + disp_pic->pts, + disp_pic->pts64, + disp_pic->pts - hw->last_pts, + hw->chunk_frame_count); + hw->last_pts = disp_pic->pts; + hw->last_pts64 = disp_pic->pts64; + hw->frame_dur = duration; + disp_pic->duration = duration; + disp_pic->repeat_cnt = repeat_cnt; + + prepare_display_buf(hw, disp_pic); hw->total_frame += repeat_cnt + 1; hw->last_vop_time_inc = vop_time_inc; - schedule_work(&hw->work); + if (vdec_frame_based(vdec) && + (frmbase_cont_bitlevel != 0) && + (hw->first_i_frame_ready)) { + u32 consume_byte, res_byte, bitcnt; + + bitcnt = READ_VREG(VIFF_BIT_CNT); + res_byte = bitcnt >> 3; + + if (hw->chunk_size > res_byte) { + if (bitcnt > frmbase_cont_bitlevel) { + consume_byte = hw->chunk_size - res_byte; + + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW, + "%s, size %d, consume %d, res %d\n", __func__, + hw->chunk_size, consume_byte, res_byte); + + if (consume_byte > VDEC_FIFO_ALIGN) { + consume_byte -= VDEC_FIFO_ALIGN; + res_byte += VDEC_FIFO_ALIGN; + } + hw->chunk_offset += consume_byte; + hw->chunk_size = res_byte; + hw->dec_result = DEC_RESULT_UNFINISH; + hw->chunk_frame_count++; + hw->unstable_pts = 1; + } else { + hw->chunk_size = 0; + hw->chunk_offset = 0; + } + } else { + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, + "error: bitbyte %d hw->chunk_size %d\n", res_byte, hw->chunk_size); + hw->chunk_size = 0; + hw->chunk_offset = 0; + } + } + vdec_schedule_work(&hw->work); } mmpeg4_debug_print(DECODE_ID(hw), PRINT_FRAME_NUM, - "%s:frame num:%d\n", __func__, hw->frame_num); + "%s: frame num:%d\n", __func__, hw->frame_num); return IRQ_HANDLED; } static irqreturn_t vmpeg4_isr(struct vdec_s *vdec, int irq) { - u32 time_increment_resolution, fixed_vop_rate; - struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)(vdec->private); + struct vdec_mpeg4_hw_s *hw = + (struct vdec_mpeg4_hw_s *)(vdec->private); if (hw->eos) return IRQ_HANDLED; - WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); - time_increment_resolution = READ_VREG(MP4_RATE); - fixed_vop_rate = time_increment_resolution >> 16; - time_increment_resolution &= 0xffff; - if (time_increment_resolution > 0 && fixed_vop_rate == 0) - hw->sys_mp4_rate = time_increment_resolution; - if (hw->vmpeg4_amstream_dec_info.rate == 0) { - if ((fixed_vop_rate != 0) && (time_increment_resolution != 0)) { - hw->vmpeg4_amstream_dec_info.rate = fixed_vop_rate * - DURATION_UNIT / - time_increment_resolution; - } else if (time_increment_resolution == 0 - && hw->sys_mp4_rate > 0) - time_increment_resolution = hw->sys_mp4_rate; - } - mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, - "resolution=%d,fvop=%d,rate=%d\n", - time_increment_resolution, fixed_vop_rate, - hw->vmpeg4_amstream_dec_info.rate); + return IRQ_WAKE_THREAD; } + +static void flush_output(struct vdec_mpeg4_hw_s * hw) +{ + struct pic_info_t *pic; + + if (hw->vfbuf_use[hw->refs[1]] > 0) { + pic = &hw->pic[hw->refs[1]]; + prepare_display_buf(hw, pic); + } +} static void vmpeg4_work(struct work_struct *work) { struct vdec_mpeg4_hw_s *hw = @@ -916,29 +1111,30 @@ static void vmpeg4_work(struct work_struct *work) * notify vdec core to switch context */ if (hw->dec_result != DEC_RESULT_DONE) - mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW, - "mmpeg4: vmpeg_work,result=%d,status=%d\n", - hw->dec_result, hw_to_vdec(hw)->next_status); + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW, + "vmpeg4_work: result=%d,status=%d\n", + hw->dec_result, hw_to_vdec(hw)->next_status); + + if (hw->dec_result == DEC_RESULT_UNFINISH) { + if (!hw->ctx_valid) + hw->ctx_valid = 1; - if ((hw->dec_result == DEC_RESULT_DONE) || - ((hw->chunk) && - (input_frame_based(&(hw_to_vdec(hw))->input)))) { + } else if ((hw->dec_result == DEC_RESULT_DONE) || + ((input_frame_based(&vdec->input)) && hw->chunk)) { if (!hw->ctx_valid) hw->ctx_valid = 1; - vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk); + vdec_vframe_dirty(vdec, hw->chunk); + hw->chunk = NULL; } else if (hw->dec_result == DEC_RESULT_AGAIN - && (hw_to_vdec(hw)->next_status != - VDEC_STATUS_DISCONNECTED)) { + && (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); - /*pr_info("%s: return\n", - __func__);*/ return; } } else if (hw->dec_result == DEC_RESULT_FORCE_EXIT) { @@ -946,37 +1142,42 @@ static void vmpeg4_work(struct work_struct *work) "%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__);*/ hw->eos = 1; if (hw->stat & STAT_VDEC_RUN) { amvdec_stop(); hw->stat &= ~STAT_VDEC_RUN; } - 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); + mmpeg4_debug_print(DECODE_ID(hw), 0, + "%s: eos flushed, frame_num %d\n", + __func__, hw->frame_num); } + if (hw->stat & STAT_VDEC_RUN) { amvdec_stop(); hw->stat &= ~STAT_VDEC_RUN; } + /*disable mbox interrupt */ + WRITE_VREG(ASSIST_MBOX1_MASK, 0); del_timer_sync(&hw->check_timer); hw->stat &= ~STAT_TIMER_ARM; /* mark itself has all HW resource released and input released */ 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); + wake_up_interruptible(&hw->wait_q); if (hw->vdec_cb) - hw->vdec_cb(hw_to_vdec(hw), hw->vdec_cb_arg); + hw->vdec_cb(vdec, hw->vdec_cb_arg); } static struct vframe_s *vmpeg_vf_peek(void *op_arg) @@ -1014,11 +1215,9 @@ static void vmpeg_vf_put(struct vframe_s *vf, void *op_arg) hw->vfbuf_use[vf->index]--; hw->put_num++; mmpeg4_debug_print(DECODE_ID(hw), PRINT_FRAME_NUM, - "%s:put num:%d\n", - __func__, hw->put_num); + "%s: put num:%d\n",__func__, hw->put_num); mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_BUFFER_DETAIL, - "index=%d, used=%d\n", - vf->index, hw->vfbuf_use[vf->index]); + "index=%d, used=%d\n", vf->index, hw->vfbuf_use[vf->index]); kfifo_put(&hw->newframe_q, (const struct vframe_s *)vf); } @@ -1048,13 +1247,14 @@ static int vmpeg_vf_states(struct vframe_states *states, void *op_arg) static int dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) { - struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)vdec->private; + struct vdec_mpeg4_hw_s *hw = + (struct vdec_mpeg4_hw_s *)vdec->private; if (!hw) return -1; - vstatus->frame_width = hw->vmpeg4_amstream_dec_info.width; - vstatus->frame_height = hw->vmpeg4_amstream_dec_info.height; + vstatus->frame_width = hw->frame_width; + vstatus->frame_height = hw->frame_height; if (0 != hw->vmpeg4_amstream_dec_info.rate) vstatus->frame_rate = DURATION_UNIT / hw->vmpeg4_amstream_dec_info.rate; @@ -1062,6 +1262,9 @@ static int dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) vstatus->frame_rate = DURATION_UNIT; vstatus->error_count = READ_VREG(MP4_ERR_COUNT); vstatus->status = hw->stat; + vstatus->frame_dur = hw->frame_dur; + snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name), + "%s", DRIVER_NAME); return 0; } @@ -1082,14 +1285,11 @@ static int vmpeg4_canvas_init(struct vdec_mpeg4_hw_s *hw) decbuf_y_size = 0x80000; decbuf_size = 0x100000; } else { - int w = hw->vmpeg4_amstream_dec_info.width; - int h = hw->vmpeg4_amstream_dec_info.height; + int w = 1920; + int h = 1088; int align_w, align_h; int max, min; - if (w == 0) - w = 1920; - if (h == 0) - h = 1088; + align_w = ALIGN(w, 64); align_h = ALIGN(h, 64); if (align_w > align_h) { @@ -1106,9 +1306,9 @@ static int vmpeg4_canvas_init(struct vdec_mpeg4_hw_s *hw) canvas_width = align_w; canvas_height = align_h; decbuf_y_size = - ALIGN(align_w * align_h, SZ_64K); + ALIGN(align_w * align_h, SZ_64K); decbuf_size = - ALIGN(align_w * align_h * 3/2, SZ_64K); + ALIGN(align_w * align_h * 3/2, SZ_64K); } else { /*1080p*/ if (h > w) { canvas_width = 1088; @@ -1140,6 +1340,12 @@ static int vmpeg4_canvas_init(struct vdec_mpeg4_hw_s *hw) } else { if (vdec->parallel_dec == 1) { unsigned tmp; + if (canvas_y(hw->canvas_spec[i]) == 0xff) { + tmp = + vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); + hw->canvas_spec[i] &= ~0xff; + hw->canvas_spec[i] |= tmp; + } if (canvas_u(hw->canvas_spec[i]) == 0xff) { tmp = vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); @@ -1147,40 +1353,33 @@ static int vmpeg4_canvas_init(struct vdec_mpeg4_hw_s *hw) hw->canvas_spec[i] |= tmp << 8; hw->canvas_spec[i] |= tmp << 16; } - if (canvas_y(hw->canvas_spec[i]) == 0xff) { - tmp = - vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); - hw->canvas_spec[i] &= ~0xff; - hw->canvas_spec[i] |= tmp; - } canvas = hw->canvas_spec[i]; } else { canvas = vdec->get_canvas(i, 2); hw->canvas_spec[i] = canvas; } - hw->canvas_config[i][0].phy_addr = - decbuf_start; - hw->canvas_config[i][0].width = - canvas_width; - hw->canvas_config[i][0].height = - canvas_height; - hw->canvas_config[i][0].block_mode = - CANVAS_BLKMODE_32X32; - - canvas_config_config(canvas_y(canvas), + hw->canvas_config[i][0].phy_addr = decbuf_start; + hw->canvas_config[i][0].width = canvas_width; + hw->canvas_config[i][0].height = canvas_height; + hw->canvas_config[i][0].block_mode = hw->blkmode; + if (hw->blkmode == CANVAS_BLKMODE_LINEAR) + hw->canvas_config[i][0].endian = 7; + else + hw->canvas_config[i][0].endian = 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; - - canvas_config_config(canvas_u(canvas), + decbuf_start + decbuf_y_size; + hw->canvas_config[i][1].width = canvas_width; + hw->canvas_config[i][1].height = (canvas_height >> 1); + hw->canvas_config[i][1].block_mode = hw->blkmode; + if (hw->blkmode == CANVAS_BLKMODE_LINEAR) + hw->canvas_config[i][1].endian = 7; + else + hw->canvas_config[i][1].endian = 0; + canvas_config_config(canvas_u(canvas), &hw->canvas_config[i][1]); } } @@ -1196,8 +1395,8 @@ static void vmpeg4_dump_state(struct vdec_s *vdec) "====== %s\n", __func__); mmpeg4_debug_print(DECODE_ID(hw), 0, "width/height (%d/%d), i_fram:%d, buffer_not_ready %d\n", - hw->vmpeg4_amstream_dec_info.width, - hw->vmpeg4_amstream_dec_info.height, + hw->frame_width, + hw->frame_height, hw->first_i_frame_ready, hw->buffer_not_ready ); @@ -1208,7 +1407,7 @@ static void vmpeg4_dump_state(struct vdec_s *vdec) mmpeg4_debug_print(DECODE_ID(hw), 0, "is_framebase(%d), eos %d, state 0x%x, dec_result 0x%x dec_frm %d\n", - input_frame_based(vdec), + vdec_frame_based(vdec), hw->eos, hw->stat, hw->dec_result, @@ -1216,7 +1415,7 @@ static void vmpeg4_dump_state(struct vdec_s *vdec) ); mmpeg4_debug_print(DECODE_ID(hw), 0, "is_framebase(%d), put_frm %d run %d not_run_ready %d input_empty %d,drop %d\n", - input_frame_based(vdec), + vdec_frame_based(vdec), hw->put_num, hw->run_count, hw->not_run_ready, @@ -1235,15 +1434,11 @@ static void vmpeg4_dump_state(struct vdec_s *vdec) state); } mmpeg4_debug_print(DECODE_ID(hw), 0, - "%s, newq(%d/%d), dispq(%d/%d) vf peek/get/put (%d/%d/%d)\n", - __func__, - kfifo_len(&hw->newframe_q), - VF_POOL_SIZE, - kfifo_len(&hw->display_q), - VF_POOL_SIZE, - hw->peek_num, - hw->get_num, - hw->put_num + "%s, newq(%d/%d), dispq(%d/%d) vf peek/get/put (%d/%d/%d)\n", + __func__, + kfifo_len(&hw->newframe_q), VF_POOL_SIZE, + kfifo_len(&hw->display_q), VF_POOL_SIZE, + hw->peek_num, hw->get_num, hw->put_num ); mmpeg4_debug_print(DECODE_ID(hw), 0, "VIFF_BIT_CNT=0x%x\n", @@ -1263,9 +1458,8 @@ static void vmpeg4_dump_state(struct vdec_s *vdec) mmpeg4_debug_print(DECODE_ID(hw), 0, "PARSER_VIDEO_WP=0x%x\n", READ_PARSER_REG(PARSER_VIDEO_WP)); - if (input_frame_based(vdec) && - debug_enable & PRINT_FRAMEBASE_DATA - ) { + if (vdec_frame_based(vdec) && + debug_enable & PRINT_FRAMEBASE_DATA) { int jj; if (hw->chunk && hw->chunk->block && hw->chunk->size > 0) { @@ -1323,8 +1517,19 @@ static void timeout_process(struct vdec_mpeg4_hw_s *hw) amvdec_stop(); hw->stat &= ~STAT_VDEC_RUN; } - mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEOUT_STATUS, - "%s decoder timeout\n", __func__); + mmpeg4_debug_print(DECODE_ID(hw), 0, + "%s decoder timeout %d\n", __func__, hw->timeout_cnt); + if (vdec_frame_based((hw_to_vdec(hw)))) { + mmpeg4_debug_print(DECODE_ID(hw), 0, + "%s frame_num %d, chunk size 0x%x, chksum 0x%x\n", + __func__, + hw->frame_num, + hw->chunk->size, + get_data_check_sum(hw, hw->chunk->size)); + } + hw->timeout_cnt++; + /* timeout: data droped, frame_num inaccurate*/ + hw->frame_num++; reset_process_time(hw); hw->first_i_frame_ready = 0; hw->dec_result = DEC_RESULT_DONE; @@ -1348,9 +1553,9 @@ 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) && + (vdec_frame_based(vdec) || + ((u32)READ_VREG(VLD_MEM_VIFIFO_LEVEL) > 0x100)) && (timeout_val > 0) && (hw->start_process_time > 0) && ((1000 * (jiffies - hw->start_process_time) / HZ) @@ -1377,17 +1582,24 @@ static void check_timer_func(unsigned long arg) static int vmpeg4_hw_ctx_restore(struct vdec_mpeg4_hw_s *hw) { - int index; - + int index, i; + void *workspace_buf = NULL; index = find_buffer(hw); - if (index < 0) - return -1; - - - if (vmpeg4_canvas_init(hw) < 0) + if (index >= DECODE_BUFFER_NUM_MAX) return -1; + if (!hw->init_flag) { + if (vmpeg4_canvas_init(hw) < 0) + return -1; + } else { + 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 @@ -1403,10 +1615,6 @@ static int vmpeg4_hw_ctx_restore(struct vdec_mpeg4_hw_s *hw) WRITE_VREG(MREG_REF1, (hw->refs[1] == -1) ? 0xffffffff : hw->canvas_spec[hw->refs[1]]); - WRITE_VREG(MREG_REF0, (hw->refs[0] == -1) ? 0xffffffff : - hw->canvas_spec[hw->refs[0]]); - WRITE_VREG(MREG_REF1, (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]); @@ -1418,6 +1626,15 @@ static int vmpeg4_hw_ctx_restore(struct vdec_mpeg4_hw_s *hw) hw->ctx_valid, index); /* notify ucode the buffer start address */ + workspace_buf = codec_mm_vmap(hw->buf_start, WORKSPACE_SIZE); + if (workspace_buf) { + /* clear to fix decoder timeout at first time */ + if (!hw->init_flag) + memset(workspace_buf, 0, WORKSPACE_SIZE); + codec_mm_dma_flush(workspace_buf, + WORKSPACE_SIZE, DMA_TO_DEVICE); + codec_mm_unmap_phyaddr(workspace_buf); + } WRITE_VREG(MEM_OFFSET_REG, hw->buf_start); /* disable PSCALE for hardware sharing */ @@ -1444,8 +1661,7 @@ static int vmpeg4_hw_ctx_restore(struct vdec_mpeg4_hw_s *hw) WRITE_VREG(MP4_PIC_WH, (hw->ctx_valid) ? hw->reg_mp4_pic_wh : - ((hw->vmpeg4_amstream_dec_info.width << 16) | - hw->vmpeg4_amstream_dec_info.height)); + ((hw->frame_width << 16) | hw->frame_height)); WRITE_VREG(MP4_SYS_RATE, hw->vmpeg4_amstream_dec_info.rate); if (hw->ctx_valid) { @@ -1460,7 +1676,7 @@ static int vmpeg4_hw_ctx_restore(struct vdec_mpeg4_hw_s *hw) WRITE_VREG(SLICE_QP, hw->reg_slice_qp); WRITE_VREG(MB_INFO, hw->reg_mb_info); - if (hw->chunk) { + if (vdec_frame_based(hw_to_vdec(hw)) && hw->chunk) { /* frame based input */ WRITE_VREG(MREG_INPUT, (hw->chunk->offset & 7) | (1<<7) | (hw->ctx_valid<<6)); @@ -1481,10 +1697,19 @@ static void vmpeg4_local_init(struct vdec_mpeg4_hw_s *hw) hw->vmpeg4_ratio64 = hw->vmpeg4_amstream_dec_info.ratio64; hw->vmpeg4_rotation = - (((unsigned long) hw->vmpeg4_amstream_dec_info.param) - >> 16) & 0xffff; + (((unsigned long)hw->vmpeg4_amstream_dec_info.param) >> 16) & 0xffff; hw->sys_mp4_rate = hw->vmpeg4_amstream_dec_info.rate; - hw->frame_width = hw->frame_height = hw->frame_dur = hw->frame_prog = 0; + hw->frame_width = hw->vmpeg4_amstream_dec_info.width; + hw->frame_height = hw->vmpeg4_amstream_dec_info.height; + hw->frame_dur = 0; + hw->frame_prog = 0; + hw->unstable_pts = + (((unsigned long) hw->vmpeg4_amstream_dec_info.param & 0x40) >> 6); + mmpeg4_debug_print(DECODE_ID(hw), 0, + "param = 0x%x unstable_pts = %d\n", + hw->vmpeg4_amstream_dec_info.param, + hw->unstable_pts); + hw->last_dec_pts = -1; hw->total_frame = 0; @@ -1495,7 +1720,8 @@ static void vmpeg4_local_init(struct vdec_mpeg4_hw_s *hw) hw->last_vop_time_inc = hw->last_duration = 0; hw->vop_time_inc_since_last_anch = 0; - + hw->last_pts = 0; + hw->last_pts64 = 0; hw->frame_num_since_last_anch = 0; hw->frame_num = 0; hw->put_num = 0; @@ -1511,7 +1737,9 @@ static void vmpeg4_local_init(struct vdec_mpeg4_hw_s *hw) hw->first_i_frame_ready = 0; hw->drop_frame_count = 0; hw->buffer_not_ready = 0; - hw->timeout_flag = 0; + hw->init_flag = 0; + hw->dec_result = DEC_RESULT_NONE; + hw->timeout_cnt = 0; for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) hw->vfbuf_use[i] = 0; @@ -1537,6 +1765,8 @@ static void vmpeg4_local_init(struct vdec_mpeg4_hw_s *hw) CODEC_MM_FLAGS_CMA_CLEAR | CODEC_MM_FLAGS_FOR_VDECODER); INIT_WORK(&hw->work, vmpeg4_work); + + init_waitqueue_head(&hw->wait_q); } static s32 vmmpeg4_init(struct vdec_mpeg4_hw_s *hw) @@ -1557,7 +1787,9 @@ static s32 vmmpeg4_init(struct vdec_mpeg4_hw_s *hw) VIDEO_DEC_FORMAT_H263) { size = get_firmware_data(VIDEO_DEC_H263_MULTI, fw->data); strncpy(fw->name, "mh263_mc", sizeof(fw->name)); - } + } else + pr_err("unsupport mpeg4 sub format %d\n", + hw->vmpeg4_amstream_dec_info.format); pr_info("mmpeg4 get fw %s, size %x\n", fw->name, size); if (size < 0) { pr_err("get firmware failed."); @@ -1592,6 +1824,7 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) { int index; struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)vdec->private; + if (hw->eos) return 0; if (vdec_stream_based(vdec) && (hw->init_flag == 0) @@ -1649,27 +1882,34 @@ static void run(struct vdec_s *vdec, unsigned long mask, void (*callback)(struct vdec_s *, void *), void *arg) { struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)vdec->private; - int save_reg = READ_VREG(POWER_CTL_VLD); - int size, ret = 0; + int size = 0, ret = 0; hw->run_count++; - /* reset everything except DOS_TOP[1] and APB_CBUS[0] */ - WRITE_VREG(DOS_SW_RESET0, 0xfffffff0); - WRITE_VREG(DOS_SW_RESET0, 0); - WRITE_VREG(POWER_CTL_VLD, save_reg); - hw->vdec_cb_arg = arg; hw->vdec_cb = callback; vdec_reset_core(vdec); - size = vdec_prepare_input(vdec, &hw->chunk); - if (size < 0) { - hw->input_empty++; - hw->dec_result = DEC_RESULT_AGAIN; - schedule_work(&hw->work); - return; - } - if (input_frame_based(vdec)) { + if ((vdec_frame_based(vdec)) && + (hw->dec_result == DEC_RESULT_UNFINISH)) { + vmpeg4_prepare_input(hw); + size = hw->chunk_size; + } else { + size = vdec_prepare_input(vdec, &hw->chunk); + if (size < 4) { /*less than start code size 00 00 01 xx*/ + hw->input_empty++; + hw->dec_result = DEC_RESULT_AGAIN; + vdec_schedule_work(&hw->work); + return; + } + if ((vdec_frame_based(vdec)) && + (hw->chunk != NULL)) { + hw->chunk_offset = hw->chunk->offset; + hw->chunk_size = hw->chunk->size; + hw->chunk_frame_count = 0; + } + } + if (vdec_frame_based(vdec) && + (debug_enable & 0xc00)) { u8 *data = NULL; if (!hw->chunk->block->is_mapped) @@ -1679,18 +1919,15 @@ static void run(struct vdec_s *vdec, unsigned long mask, data = ((u8 *)hw->chunk->block->start_virt) + hw->chunk->offset; - if (debug_enable & PRINT_FLAG_VDEC_STATUS - ) { - mmpeg4_debug_print(DECODE_ID(hw), 0, + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, "%s: size 0x%x sum 0x%x %02x %02x %02x %02x %02x %02x .. %02x %02x %02x %02x\n", __func__, size, get_data_check_sum(hw, size), data[0], data[1], data[2], data[3], data[4], data[5], data[size - 4], data[size - 3], data[size - 2], data[size - 1]); - } - if (debug_enable & PRINT_FRAMEBASE_DATA - ) { + + if (debug_enable & PRINT_FRAMEBASE_DATA) { int jj; for (jj = 0; jj < size; jj++) { @@ -1710,25 +1947,16 @@ static void run(struct vdec_s *vdec, unsigned long mask, if (!hw->chunk->block->is_mapped) codec_mm_unmap_phyaddr(data); - } else - mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, - "%s: %x %x %x %x %x size 0x%x\n", - __func__, - READ_VREG(VLD_MEM_VIFIFO_LEVEL), - READ_VREG(VLD_MEM_VIFIFO_WP), - READ_VREG(VLD_MEM_VIFIFO_RP), - READ_PARSER_REG(PARSER_VIDEO_RP), - READ_PARSER_REG(PARSER_VIDEO_WP), - size); + } mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW, - "%s,%d, size=%d, %x %x %x %x %x\n", - __func__, __LINE__, size, - READ_VREG(VLD_MEM_VIFIFO_LEVEL), - READ_VREG(VLD_MEM_VIFIFO_WP), - READ_VREG(VLD_MEM_VIFIFO_RP), - READ_PARSER_REG(PARSER_VIDEO_RP), - READ_PARSER_REG(PARSER_VIDEO_WP)); + "%s, size=%d, %x %x %x %x %x\n", + __func__, size, + READ_VREG(VLD_MEM_VIFIFO_LEVEL), + READ_VREG(VLD_MEM_VIFIFO_WP), + READ_VREG(VLD_MEM_VIFIFO_RP), + READ_PARSER_REG(PARSER_VIDEO_RP), + READ_PARSER_REG(PARSER_VIDEO_WP)); hw->dec_result = DEC_RESULT_NONE; if (vdec->mc_loaded) { @@ -1743,7 +1971,7 @@ static void run(struct vdec_s *vdec, unsigned long mask, pr_err("[%d] %s: the %s fw loading failed, err: %x\n", vdec->id, hw->fw->name, tee_enabled() ? "TEE" : "local", ret); hw->dec_result = DEC_RESULT_FORCE_EXIT; - schedule_work(&hw->work); + vdec_schedule_work(&hw->work); return; } vdec->mc_loaded = 1; @@ -1753,9 +1981,14 @@ static void run(struct vdec_s *vdec, unsigned long mask, hw->dec_result = DEC_RESULT_ERROR; mmpeg4_debug_print(DECODE_ID(hw), 0, "amvdec_mpeg4: error HW context restore\n"); - schedule_work(&hw->work); + vdec_schedule_work(&hw->work); return; } + if (vdec_frame_based(vdec)) { + size = hw->chunk_size + + (hw->chunk_offset & (VDEC_FIFO_ALIGN - 1)); + WRITE_VREG(VIFF_BIT_CNT, size * 8); + } hw->input_empty = 0; hw->last_vld_level = 0; start_process_time(hw); @@ -1765,6 +1998,7 @@ static void run(struct vdec_s *vdec, unsigned long mask, amvdec_start(); hw->stat |= STAT_VDEC_RUN; + hw->init_flag = 1; mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL); } @@ -1796,7 +2030,7 @@ static void reset(struct vdec_s *vdec) vmpeg4_local_init(hw); - hw->ctx_valid = false; + hw->ctx_valid = 0; } static int ammvdec_mpeg4_probe(struct platform_device *pdev) @@ -1804,8 +2038,6 @@ static int ammvdec_mpeg4_probe(struct platform_device *pdev) struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; struct vdec_mpeg4_hw_s *hw = NULL; - pr_info("%s [%d] probe start.\n", __func__, pdev->id); - if (pdata == NULL) { pr_err("%s memory resource undefined.\n", __func__); return -EFAULT; @@ -1846,46 +2078,32 @@ static int ammvdec_mpeg4_probe(struct platform_device *pdev) platform_set_drvdata(pdev, pdata); hw->platform_dev = pdev; + hw->blkmode = CANVAS_BLKMODE_32X32; -/* - hw->cma_dev = pdata->cma_dev; - hw->cma_alloc_count = PAGE_ALIGN(DEFAULT_MEM_SIZE) / PAGE_SIZE; - hw->cma_alloc_addr = codec_mm_alloc_for_dma(MEM_NAME, - hw->cma_alloc_count, - 4, CODEC_MM_FLAGS_FOR_VDECODER); - - if (!hw->cma_alloc_addr) { - pr_err("codec_mm alloc failed, request buf size 0x%lx\n", - hw->cma_alloc_count * PAGE_SIZE); - hw->cma_alloc_count = 0; - if (hw) { + + if (pdata->sys_info) { + hw->vmpeg4_amstream_dec_info = *pdata->sys_info; + if ((hw->vmpeg4_amstream_dec_info.height != 0) && + (hw->vmpeg4_amstream_dec_info.width > + (MAX_MPEG4_SUPPORT_SIZE/hw->vmpeg4_amstream_dec_info.height))) { + pr_info("ammvdec_mpeg4: oversize, unsupport: %d*%d\n", + hw->vmpeg4_amstream_dec_info.width, + hw->vmpeg4_amstream_dec_info.height); + pdata->dec_status = NULL; vfree((void *)hw); hw = NULL; + return -EFAULT; } - return -ENOMEM; + mmpeg4_debug_print(DECODE_ID(hw), 0, + "sysinfo: %d x %d, rate: %d\n", + hw->vmpeg4_amstream_dec_info.width, + hw->vmpeg4_amstream_dec_info.height, + hw->vmpeg4_amstream_dec_info.rate); } - hw->buf_start = hw->cma_alloc_addr; - hw->buf_size = DEFAULT_MEM_SIZE; -*/ - if (pdata->sys_info) - hw->vmpeg4_amstream_dec_info = *pdata->sys_info; - - mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, - "W:%d,H:%d,rate=%d\n", - hw->vmpeg4_amstream_dec_info.width, - hw->vmpeg4_amstream_dec_info.height, - hw->vmpeg4_amstream_dec_info.rate); - hw->vmpeg4_amstream_dec_info.height = 0; - hw->vmpeg4_amstream_dec_info.width = 0; if (vmmpeg4_init(hw) < 0) { pr_err("%s init failed.\n", __func__); -/* - if (hw->cma_alloc_addr) { - codec_mm_free_for_dma(MEM_NAME, hw->cma_alloc_addr); - hw->cma_alloc_count = 0; - } -*/ + if (hw) { vfree((void *)hw); hw = NULL; @@ -1893,6 +2111,7 @@ static int ammvdec_mpeg4_probe(struct platform_device *pdev) 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 { @@ -1900,6 +2119,9 @@ static int ammvdec_mpeg4_probe(struct platform_device *pdev) | CORE_MASK_COMBINE); } + mmpeg4_debug_print(DECODE_ID(hw), 0, + "%s end.\n", __func__); + return 0; } @@ -1911,14 +2133,19 @@ static int ammvdec_mpeg4_remove(struct platform_device *pdev) struct vdec_s *vdec = hw_to_vdec(hw); int i; - vmpeg4_stop(hw); - /* - if (hw->cma_alloc_addr) { - pr_info("codec_mm release buffer 0x%lx\n", hw->cma_alloc_addr); - codec_mm_free_for_dma(MEM_NAME, hw->cma_alloc_addr); - hw->cma_alloc_count = 0; + if (vdec->next_status == VDEC_STATUS_DISCONNECTED + && (vdec->status == VDEC_STATUS_ACTIVE)) { + mmpeg4_debug_print(DECODE_ID(hw), 0, + "%s force exit %d\n", __func__, __LINE__); + hw->dec_result = DEC_RESULT_FORCE_EXIT; + vdec_schedule_work(&hw->work); + wait_event_interruptible_timeout(hw->wait_q, + (vdec->status == VDEC_STATUS_CONNECTED), + msecs_to_jiffies(1000)); /* wait for work done */ } - */ + + vmpeg4_stop(hw); + if (vdec->parallel_dec == 1) vdec_core_release(hw_to_vdec(hw), CORE_MASK_VDEC_1); else @@ -1932,10 +2159,7 @@ static int ammvdec_mpeg4_remove(struct platform_device *pdev) } } - pr_info("pts hit %d, pts missed %d, i hit %d, missed %d\n", hw->pts_hit, - hw->pts_missed, hw->pts_i_hit, hw->pts_i_missed); - pr_info("total frame %d, rate %d\n", hw->total_frame, - hw->vmpeg4_amstream_dec_info.rate); + mmpeg4_debug_print(DECODE_ID(hw), 0, "%s\n", __func__); vfree((void *)hw); hw = NULL; @@ -1985,6 +2209,9 @@ module_param(debug_enable, uint, 0664); MODULE_PARM_DESC(debug_enable, "\n ammvdec_mpeg4 debug enable\n"); +module_param(frmbase_cont_bitlevel, uint, 0664); +MODULE_PARM_DESC(frmbase_cont_bitlevel, "\nfrmbase_cont_bitlevel\n"); + module_param(radr, uint, 0664); MODULE_PARM_DESC(radr, "\nradr\n"); @@ -1998,10 +2225,18 @@ module_param_array(max_process_time, uint, &max_decode_instance_num, 0664); module_param(pre_decode_buf_level, int, 0664); MODULE_PARM_DESC(pre_decode_buf_level, - "\n ammvdec_ mpeg4 pre_decode_buf_level\n"); + "\n ammvdec_mpeg4 pre_decode_buf_level\n"); + +module_param(start_decode_buf_level, int, 0664); +MODULE_PARM_DESC(start_decode_buf_level, + "\n ammvdec_mpeg4 start_decode_buf_level\n"); module_param(udebug_flag, uint, 0664); MODULE_PARM_DESC(udebug_flag, "\n ammvdec_mpeg4 udebug_flag\n"); + +module_param(without_display_mode, uint, 0664); +MODULE_PARM_DESC(without_display_mode, "\n ammvdec_mpeg4 without_display_mode\n"); + module_init(ammvdec_mpeg4_driver_init_module); module_exit(ammvdec_mpeg4_driver_remove_module); |