author | Liang Ji <liang.ji@amlogic.com> | 2020-01-16 07:32:35 (GMT) |
---|---|---|
committer | Liang Ji <liang.ji@amlogic.com> | 2020-01-16 07:43:59 (GMT) |
commit | aac901b9cf2199375959d6ca4467ae09efa96898 (patch) | |
tree | 86717d325b4abbdea84edd1c407e17cf4bf07548 | |
parent | c94bdbfa64b4786a4f4984b5792155f216b8fe87 (diff) | |
parent | 49c06502c900f3fd27e878e04881d499b4788396 (diff) | |
download | media_modules-aac901b9cf2199375959d6ca4467ae09efa96898.zip media_modules-aac901b9cf2199375959d6ca4467ae09efa96898.tar.gz media_modules-aac901b9cf2199375959d6ca4467ae09efa96898.tar.bz2 |
Merge branch 'amlogic/sabrina' into sabrina
Change-Id: I4b846532af1c37958576110282004672d7d8182e
Signed-off-by: Liang Ji <liang.ji@amlogic.com>
36 files changed, 3563 insertions, 1276 deletions
diff --git a/drivers/amvdec_ports/aml_vcodec_adapt.c b/drivers/amvdec_ports/aml_vcodec_adapt.c index f4bfc55..da5637d 100644 --- a/drivers/amvdec_ports/aml_vcodec_adapt.c +++ b/drivers/amvdec_ports/aml_vcodec_adapt.c @@ -120,7 +120,7 @@ static void set_default_params(struct aml_vdec_adapt *vdec) vdec->dec_prop.param = (void *)sync_mode; vdec->dec_prop.format = vdec->format; vdec->dec_prop.width = 1920; - vdec->dec_prop.height = 1080; + vdec->dec_prop.height = 1088; vdec->dec_prop.rate = 3200; } @@ -511,6 +511,11 @@ static void set_vdec_properity(struct vdec_s *vdec, vdec->port->flag = vdec->port_flag; ada_ctx->vfm_path = vdec->frame_base_video_path; + + vdec->config_len = ada_ctx->config.length > + PAGE_SIZE ? PAGE_SIZE : ada_ctx->config.length; + memcpy(vdec->config, ada_ctx->config.buf, vdec->config_len); + ada_ctx->vdec = vdec; } @@ -660,14 +665,11 @@ int vdec_vbuf_write(struct aml_vdec_adapt *ada_ctx, return ret; } -int is_need_to_buf(struct aml_vdec_adapt *ada_ctx) +bool vdec_input_full(struct aml_vdec_adapt *ada_ctx) { struct vdec_s *vdec = ada_ctx->vdec; - if (vdec->input.have_frame_num > 8) - return 0; - else - return 1; + return (vdec->input.have_frame_num > 600) ? true : false; } int vdec_vframe_write(struct aml_vdec_adapt *ada_ctx, @@ -690,7 +692,7 @@ int vdec_vframe_write(struct aml_vdec_adapt *ada_ctx, /* dump to file */ dump_write(buf, count); #endif - aml_v4l2_debug(4, "[%d] write frames, vbuf: %p, size: %u, ret: %d, crc: %x", + aml_v4l2_debug(3, "[%d] write frames, vbuf: %p, size: %u, ret: %d, crc: %x", ada_ctx->ctx->id, buf, count, ret, crc32_le(0, buf, count)); return ret; @@ -704,14 +706,22 @@ void aml_decoder_flush(struct aml_vdec_adapt *ada_ctx) vdec_set_eos(vdec, true); } -int aml_codec_reset(struct aml_vdec_adapt *ada_ctx) +int aml_codec_reset(struct aml_vdec_adapt *ada_ctx, int *mode) { struct vdec_s *vdec = ada_ctx->vdec; int ret = 0; if (vdec) { vdec_set_eos(vdec, false); - ret = vdec_reset(vdec); + + if (*mode == V4L_RESET_MODE_NORMAL && + vdec->input.have_frame_num == 0) + *mode = V4L_RESET_MODE_LIGHT; + + aml_v4l2_debug(2, "%s, reset mode: %d\n", __func__, *mode); + + ret = vdec_v4l2_reset(vdec, *mode); + *mode = V4L_RESET_MODE_NORMAL; } return ret; @@ -742,3 +752,12 @@ int vdec_frame_number(struct aml_vdec_adapt *ada_ctx) else return -1; } + +void v4l2_config_vdec_parm(struct aml_vdec_adapt *ada_ctx, u8 *data, u32 len) +{ + struct vdec_s *vdec = ada_ctx->vdec; + + vdec->config_len = len > PAGE_SIZE ? PAGE_SIZE : len; + memcpy(vdec->config, data, vdec->config_len); +} + diff --git a/drivers/amvdec_ports/aml_vcodec_adapt.h b/drivers/amvdec_ports/aml_vcodec_adapt.h index 5a69312..1f8afdd 100644 --- a/drivers/amvdec_ports/aml_vcodec_adapt.h +++ b/drivers/amvdec_ports/aml_vcodec_adapt.h @@ -38,6 +38,7 @@ struct aml_vdec_adapt { struct vdec_s *vdec; struct stream_port_s port; struct dec_sysinfo dec_prop; + struct v4l2_config_parm config; int video_type; char *recv_name; int vfm_path; @@ -53,11 +54,11 @@ int vdec_vbuf_write(struct aml_vdec_adapt *ada_ctx, int vdec_vframe_write(struct aml_vdec_adapt *ada_ctx, const char *buf, unsigned int count, u64 timestamp); -int is_need_to_buf(struct aml_vdec_adapt *ada_ctx); +bool vdec_input_full(struct aml_vdec_adapt *ada_ctx); void aml_decoder_flush(struct aml_vdec_adapt *ada_ctx); -int aml_codec_reset(struct aml_vdec_adapt *ada_ctx); +int aml_codec_reset(struct aml_vdec_adapt *ada_ctx, int *flag); extern void dump_write(const char __user *buf, size_t count); diff --git a/drivers/amvdec_ports/aml_vcodec_dec.c b/drivers/amvdec_ports/aml_vcodec_dec.c index 9c34b49..ec6d6e3 100644 --- a/drivers/amvdec_ports/aml_vcodec_dec.c +++ b/drivers/amvdec_ports/aml_vcodec_dec.c @@ -34,6 +34,11 @@ #include <linux/spinlock.h> #include "aml_vcodec_vfm.h" +#include "../frame_provider/decoder/utils/decoder_bmmu_box.h" +#include "../frame_provider/decoder/utils/decoder_mmu_box.h" + +#define KERNEL_ATRACE_TAG KERNEL_ATRACE_TAG_V4L2 +#include <trace/events/meson_atrace.h> #define OUT_FMT_IDX 0 //default h264 #define CAP_FMT_IDX 8 //capture nv21 @@ -157,6 +162,9 @@ static const struct aml_codec_framesizes aml_vdec_framesizes[] = { extern bool multiplanar; +extern int dmabuf_fd_install_data(int fd, void* data, u32 size); +extern bool is_v4l2_buf_file(struct file *file); + static ulong aml_vcodec_ctx_lock(struct aml_vcodec_ctx *ctx) { ulong flags; @@ -198,16 +206,34 @@ static struct aml_q_data *aml_vdec_get_q_data(struct aml_vcodec_ctx *ctx, return &ctx->q_data[AML_Q_DATA_DST]; } -static void aml_vdec_queue_res_chg_event(struct aml_vcodec_ctx *ctx) +void aml_vdec_dispatch_event(struct aml_vcodec_ctx *ctx, u32 changes) { - static const struct v4l2_event ev_src_ch = { - .type = V4L2_EVENT_SOURCE_CHANGE, - .u.src_change.changes = - V4L2_EVENT_SRC_CH_RESOLUTION, - }; + struct v4l2_event event = {0}; - aml_v4l2_debug(4, "[%d] %s()", ctx->id, __func__); - v4l2_event_queue_fh(&ctx->fh, &ev_src_ch); + if (ctx->receive_cmd_stop) { + ctx->state = AML_STATE_ABORT; + ATRACE_COUNTER("v4l2_state", ctx->state); + changes = V4L2_EVENT_REQUEST_EXIT; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ABORT)", + ctx->id, __func__); + } + + switch (changes) { + case V4L2_EVENT_SRC_CH_RESOLUTION: + case V4L2_EVENT_SRC_CH_HDRINFO: + case V4L2_EVENT_REQUEST_RESET: + case V4L2_EVENT_REQUEST_EXIT: + event.type = V4L2_EVENT_SOURCE_CHANGE; + event.u.src_change.changes = changes; + break; + default: + pr_err("unsupport dispatch event %x\n", changes); + return; + } + + v4l2_event_queue_fh(&ctx->fh, &event); + aml_v4l2_debug(3, "[%d] %s() changes: %x", + ctx->id, __func__, changes); } static void aml_vdec_flush_decoder(struct aml_vcodec_ctx *ctx) @@ -235,9 +261,9 @@ static void aml_vdec_pic_info_update(struct aml_vcodec_ctx *ctx) return; } - if ((ctx->last_decoded_picinfo.visible_width == ctx->picinfo.visible_width) || + /*if ((ctx->last_decoded_picinfo.visible_width == ctx->picinfo.visible_width) || (ctx->last_decoded_picinfo.visible_height == ctx->picinfo.visible_height)) - return; + return;*/ aml_v4l2_debug(4, "[%d]-> new(%d,%d), old(%d,%d), real(%d,%d)", ctx->id, ctx->last_decoded_picinfo.visible_width, @@ -255,6 +281,33 @@ static void aml_vdec_pic_info_update(struct aml_vcodec_ctx *ctx) ctx->picinfo = ctx->last_decoded_picinfo; } +void vdec_frame_buffer_release(void *data) +{ + struct file_private_data *priv_data = + (struct file_private_data *) data; + struct vframe_s *vf = &priv_data->vf; + + if (decoder_bmmu_box_valide_check(vf->mm_box.bmmu_box)) { + decoder_bmmu_box_free_idx(vf->mm_box.bmmu_box, + vf->mm_box.bmmu_idx); + decoder_bmmu_try_to_release_box(vf->mm_box.bmmu_box); + } + + if (decoder_mmu_box_valide_check(vf->mm_box.mmu_box)) { + decoder_mmu_box_free_idx(vf->mm_box.mmu_box, + vf->mm_box.mmu_idx); + decoder_mmu_try_to_release_box(vf->mm_box.mmu_box); + } + + aml_v4l2_debug(2, "%s vf idx: %d, bmmu idx: %d, bmmu_box: %p", + __func__, vf->index, vf->mm_box.bmmu_idx, vf->mm_box.bmmu_box); + aml_v4l2_debug(2, "%s vf idx: %d, mmu_idx: %d, mmu_box: %p", + __func__, vf->index, vf->mm_box.mmu_idx, vf->mm_box.mmu_box); + + memset(data, 0, sizeof(struct file_private_data)); + kfree(data); +} + int get_fb_from_queue(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer **out_fb) { ulong flags; @@ -265,6 +318,11 @@ int get_fb_from_queue(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer **out_ flags = aml_vcodec_ctx_lock(ctx); + if (ctx->state == AML_STATE_ABORT) { + aml_vcodec_ctx_unlock(ctx, flags); + return -1; + } + dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); if (!dst_buf) { aml_vcodec_ctx_unlock(ctx, flags); @@ -283,7 +341,7 @@ int get_fb_from_queue(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer **out_ pfb->mem_type = VDEC_SCATTER_MEMORY_TYPE; pfb->status = FB_ST_NORMAL; } else if (dst_buf->num_planes == 1) { - pfb = &dst_buf_info->frame_buffer; + pfb = &dst_buf_info->frame_buffer; pfb->m.mem[0].dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0); pfb->m.mem[0].addr = dma_to_phys(v4l_get_dev_from_codec_mm(), pfb->m.mem[0].dma_addr); pfb->m.mem[0].size = ctx->picinfo.y_len_sz + ctx->picinfo.c_len_sz; @@ -345,6 +403,8 @@ int get_fb_from_queue(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer **out_ info = container_of(pfb, struct aml_video_dec_buf, frame_buffer); + ctx->cap_pool.seq[ctx->cap_pool.out++] = + (V4L_CAP_BUFF_IN_DEC << 16 | dst_buf->index); v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); aml_vcodec_ctx_unlock(ctx, flags); @@ -427,6 +487,7 @@ void trans_vframe_to_user(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer *f pr_info("[%d] recevie a empty frame. idx: %d, state: %d\n", ctx->id, dstbuf->vb.vb2_buf.index, dstbuf->vb.vb2_buf.state); + ATRACE_COUNTER("v4l2_eos", 0); } aml_v4l2_debug(4, "[%d] receive vbuf idx: %d, state: %d", @@ -435,8 +496,11 @@ void trans_vframe_to_user(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer *f if (dstbuf->vb.vb2_buf.state == VB2_BUF_STATE_ACTIVE) { /* binding vframe handle. */ - if (fb->mem_type == VDEC_SCATTER_MEMORY_TYPE) - dstbuf->vb.private = fb->m.vf_fd; + vf->flag |= VFRAME_FLAG_VIDEO_LINEAR; + ATRACE_COUNTER("v4l2_from", vf->index_disp); + dstbuf->privdata.vf = *vf; + dstbuf->privdata.vf.omx_index = + dstbuf->vb.vb2_buf.index; v4l2_m2m_buf_done(&dstbuf->vb, VB2_BUF_STATE_DONE); } @@ -445,6 +509,7 @@ void trans_vframe_to_user(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer *f if (ctx->state == AML_STATE_FLUSHING && ctx->has_receive_eos) { ctx->state = AML_STATE_FLUSHED; + ATRACE_COUNTER("v4l2_state", ctx->state); aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_FLUSHED)", ctx->id, __func__); } @@ -452,6 +517,11 @@ void trans_vframe_to_user(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer *f if (dstbuf->lastframe && ctx->q_data[AML_Q_DATA_SRC].resolution_changed) { + + /* make the run to stanby until new buffs to enque. */ + ctx->v4l_codec_dpb_ready = false; + ctx->reset_flag = V4L_RESET_MODE_LIGHT; + /* * After all buffers containing decoded frames from * before the resolution change point ready to be @@ -460,7 +530,7 @@ void trans_vframe_to_user(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer *f * type V4L2_EVENT_SRC_CH_RESOLUTION, also the upper * layer will get new information from cts->picinfo. */ - aml_vdec_queue_res_chg_event(ctx); + aml_vdec_dispatch_event(ctx, V4L2_EVENT_SRC_CH_RESOLUTION); } ctx->decoded_frame_cnt++; @@ -486,6 +556,23 @@ static int get_display_buffer(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffe return ret; } +static void aml_check_dpb_ready(struct aml_vcodec_ctx *ctx) +{ + if (!ctx->v4l_codec_dpb_ready) { + /* + * make sure enough dst bufs for decoding, and + * the backend maybe hold 4 frms so need to minus 4. + */ + if ((ctx->dpb_size) && (ctx->cap_pool.in >= ctx->dpb_size - 4)) + ctx->v4l_codec_dpb_ready = true; + + aml_v4l2_debug(2, "[%d] %s() dpb: %d, ready: %d, used: %d, dpb is ready: %s", + ctx->id, __func__, ctx->dpb_size, + v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx), + ctx->cap_pool.out, ctx->v4l_codec_dpb_ready ? "yes" : "no"); + } +} + static int is_vdec_ready(struct aml_vcodec_ctx *ctx) { struct aml_vcodec_dev *dev = ctx->dev; @@ -498,22 +585,10 @@ static int is_vdec_ready(struct aml_vcodec_ctx *ctx) } if (ctx->state == AML_STATE_PROBE) { - int buf_ready_num; - - /* is there enough dst bufs for decoding? */ - buf_ready_num = v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx); - if ((buf_ready_num + ctx->buf_used_count) < ctx->dpb_size) { - aml_v4l2_debug(4, "[%d] Not enough dst bufs, num: %d.", - ctx->id, buf_ready_num); - v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); - v4l2_m2m_try_schedule(ctx->m2m_ctx); - msleep(60); - return 0; - } - mutex_lock(&ctx->state_lock); if (ctx->state == AML_STATE_PROBE) { ctx->state = AML_STATE_READY; + ATRACE_COUNTER("v4l2_state", ctx->state); ctx->v4l_codec_ready = true; wake_up_interruptible(&ctx->wq); aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_READY)", @@ -527,12 +602,16 @@ static int is_vdec_ready(struct aml_vcodec_ctx *ctx) if (ctx->m2m_ctx->out_q_ctx.q.streaming && ctx->m2m_ctx->cap_q_ctx.q.streaming) { ctx->state = AML_STATE_ACTIVE; + ATRACE_COUNTER("v4l2_state", ctx->state); aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ACTIVE)", ctx->id, __func__); } } mutex_unlock(&ctx->state_lock); + /* check dpb ready */ + //aml_check_dpb_ready(ctx); + return 1; } @@ -548,6 +627,25 @@ static bool is_enough_work_items(struct aml_vcodec_ctx *ctx) return true; } +static void aml_wait_dpb_ready(struct aml_vcodec_ctx *ctx) +{ + ulong expires; + + expires = jiffies + msecs_to_jiffies(1000); + while (!ctx->v4l_codec_dpb_ready) { + u32 ready_num = 0; + + if (time_after(jiffies, expires)) { + pr_err("the DPB state has not ready.\n"); + break; + } + + ready_num = v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx); + if ((ready_num + ctx->buf_used_count) >= ctx->dpb_size) + ctx->v4l_codec_dpb_ready = true; + } +} + static void aml_vdec_worker(struct work_struct *work) { struct aml_vcodec_ctx *ctx = @@ -589,22 +687,32 @@ static void aml_vdec_worker(struct work_struct *work) if (src_buf_info->lastframe) { /*the empty data use to flushed the decoder.*/ - aml_v4l2_debug(3, "[%d] Got empty flush input buffer.", ctx->id); - - src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); - v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); + aml_v4l2_debug(2, "[%d] Got empty flush input buffer.", ctx->id); - /* sets eos data for vdec input. */ - aml_vdec_flush_decoder(ctx); + /* + * when inputs a small amount of src buff, then soon to + * switch state FLUSHING, must to wait the DBP to be ready. + */ + if (!ctx->v4l_codec_dpb_ready) { + v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); + goto out; + } mutex_lock(&ctx->state_lock); if (ctx->state == AML_STATE_ACTIVE) { ctx->state = AML_STATE_FLUSHING;// prepare flushing - aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_FLUSHING)", + ATRACE_COUNTER("v4l2_state", ctx->state); + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_FLUSHING-LASTFRM)", ctx->id, __func__); } mutex_unlock(&ctx->state_lock); + src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); + v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); + + /* sets eos data for vdec input. */ + aml_vdec_flush_decoder(ctx); + goto out; } @@ -643,6 +751,9 @@ static void aml_vdec_worker(struct work_struct *work) aml_v4l2_err("[%d] %s() error processing src data. %d.", ctx->id, __func__, ret); } else if (res_chg) { + /* wait the DPB state to be ready. */ + aml_wait_dpb_ready(ctx); + src_buf_info->used = false; aml_vdec_pic_info_update(ctx); /* @@ -651,11 +762,11 @@ static void aml_vdec_worker(struct work_struct *work) * remaining buffers from before the resolution change * point, so call flush decode here */ - aml_vdec_flush_decoder(ctx); mutex_lock(&ctx->state_lock); if (ctx->state == AML_STATE_ACTIVE) { ctx->state = AML_STATE_FLUSHING;// prepare flushing - aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_FLUSHING)", + ATRACE_COUNTER("v4l2_state", ctx->state); + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_FLUSHING-RESCHG)", ctx->id, __func__); } mutex_unlock(&ctx->state_lock); @@ -663,6 +774,8 @@ static void aml_vdec_worker(struct work_struct *work) ctx->q_data[AML_Q_DATA_SRC].resolution_changed = true; v4l2_m2m_job_pause(dev->m2m_dev_dec, ctx->m2m_ctx); + aml_vdec_flush_decoder(ctx); + goto out; } @@ -671,23 +784,6 @@ out: return; } -void wait_vcodec_ending(struct aml_vcodec_ctx *ctx) -{ - struct aml_vcodec_dev *dev = ctx->dev; - - /* pause inject output data to vdec. */ - v4l2_m2m_job_pause(dev->m2m_dev_dec, ctx->m2m_ctx); - - /* flush worker. */ - flush_workqueue(dev->decode_workqueue); - - /* wait reset worker ending. */ - if (ctx->state == AML_STATE_RESET) { - wait_for_completion_timeout(&ctx->comp, - msecs_to_jiffies(200)); - } -} - static void aml_vdec_reset(struct aml_vcodec_ctx *ctx) { if (ctx->state == AML_STATE_ABORT) { @@ -696,8 +792,9 @@ static void aml_vdec_reset(struct aml_vcodec_ctx *ctx) goto out; } - if (aml_codec_reset(ctx->ada_ctx)) { + if (aml_codec_reset(ctx->ada_ctx, &ctx->reset_flag)) { ctx->state = AML_STATE_ABORT; + ATRACE_COUNTER("v4l2_state", ctx->state); aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ABORT)", ctx->id, __func__); goto out; @@ -705,18 +802,42 @@ static void aml_vdec_reset(struct aml_vcodec_ctx *ctx) if (ctx->state == AML_STATE_RESET) { ctx->state = AML_STATE_PROBE; + ATRACE_COUNTER("v4l2_state", ctx->state); aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_PROBE)", ctx->id, __func__); + aml_v4l2_debug(0, "[%d] %s() dpb: %d, ready: %d, used: %d", + ctx->id, __func__, ctx->dpb_size, + v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx), ctx->buf_used_count); + /* vdec has ready to decode subsequence data of new resolution. */ ctx->q_data[AML_Q_DATA_SRC].resolution_changed = false; v4l2_m2m_job_resume(ctx->dev->m2m_dev_dec, ctx->m2m_ctx); } + out: complete(&ctx->comp); return; } +void wait_vcodec_ending(struct aml_vcodec_ctx *ctx) +{ + struct aml_vcodec_dev *dev = ctx->dev; + + /* pause inject output data to vdec. */ + v4l2_m2m_job_pause(dev->m2m_dev_dec, ctx->m2m_ctx); + + /* flush worker. */ + flush_workqueue(dev->decode_workqueue); + + ctx->v4l_codec_ready = false; + ctx->v4l_codec_dpb_ready = false; + + /* stop decoder. */ + if (ctx->state > AML_STATE_INIT) + aml_vdec_reset(ctx); +} + void try_to_capture(struct aml_vcodec_ctx *ctx) { int ret = 0; @@ -785,6 +906,7 @@ int aml_thread_start(struct aml_vcodec_ctx *ctx, aml_thread_func func, enum aml_thread_type type, const char *thread_name) { struct aml_vdec_thread *thread; + struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 }; int ret = 0; thread = kzalloc(sizeof(*thread), GFP_KERNEL); @@ -802,6 +924,7 @@ int aml_thread_start(struct aml_vcodec_ctx *ctx, aml_thread_func func, thread->task = NULL; goto err; } + sched_setscheduler_nocheck(thread->task, SCHED_FIFO, ¶m); list_add(&thread->node, &ctx->vdec_thread_list); @@ -860,16 +983,25 @@ static int vidioc_decoder_cmd(struct file *file, void *priv, if (ret) return ret; - aml_v4l2_debug(3, "[%d] %s() [%d], cmd: %u", + aml_v4l2_debug(2, "[%d] %s() [%d], cmd: %u", ctx->id, __func__, __LINE__, cmd->cmd); dst_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, multiplanar ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : V4L2_BUF_TYPE_VIDEO_CAPTURE); switch (cmd->cmd) { case V4L2_DEC_CMD_STOP: - - if (ctx->state != AML_STATE_ACTIVE) - return 0; + ATRACE_COUNTER("v4l2_stop", 0); + if (ctx->state != AML_STATE_ACTIVE) { + if (ctx->state >= AML_STATE_IDLE && + ctx->state <= AML_STATE_PROBE) { + ctx->state = AML_STATE_ABORT; + ATRACE_COUNTER("v4l2_state", ctx->state); + aml_vdec_dispatch_event(ctx, V4L2_EVENT_REQUEST_EXIT); + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ABORT)", + ctx->id, __func__); + return 0; + } + } src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); @@ -886,10 +1018,7 @@ static int vidioc_decoder_cmd(struct file *file, void *priv, /* flush src */ v4l2_m2m_buf_queue(ctx->m2m_ctx, &ctx->empty_flush_buf->vb); v4l2_m2m_try_schedule(ctx->m2m_ctx);//pay attention - - /* remark cmd use to distinguish stop or seek. */ ctx->receive_cmd_stop = true; - break; case V4L2_DEC_CMD_START: @@ -910,42 +1039,45 @@ static int vidioc_decoder_streamon(struct file *file, void *priv, struct v4l2_fh *fh = file->private_data; struct aml_vcodec_ctx *ctx = fh_to_ctx(fh); struct vb2_queue *q; - int ret = 0; - - ret = v4l2_m2m_ioctl_streamon(file, priv, i); q = v4l2_m2m_get_vq(fh->m2m_ctx, i); - if (!V4L2_TYPE_IS_OUTPUT(q->type)) { - mutex_lock(&ctx->state_lock); - - /* - * if receive the cmd is not V4L2_DEC_CMD_STOP - * that request should be seek not stop, thus igorn status - * AML_STATE_FLUSHING and AML_STATE_FLUSHED. - */ - - if (ctx->state == AML_STATE_FLUSHED || - ctx->state == AML_STATE_FLUSHING || //???? - (ctx->state == AML_STATE_ACTIVE && - !ctx->receive_cmd_stop)) { - if (!V4L2_TYPE_IS_OUTPUT(q->type)) { - /*the short source will be fasted into flushing state. - then switch to abort state that caused seek failed.*/ - if (ctx->state == AML_STATE_FLUSHING) - ctx->receive_cmd_stop = false; - + if (ctx->is_stream_off) { + mutex_lock(&ctx->state_lock); + if ((ctx->state == AML_STATE_ACTIVE || + ctx->state == AML_STATE_FLUSHING || + ctx->state == AML_STATE_FLUSHED) || + (ctx->reset_flag == V4L_RESET_MODE_LIGHT)) { ctx->state = AML_STATE_RESET; + ATRACE_COUNTER("v4l2_state", ctx->state); ctx->v4l_codec_ready = false; + ctx->v4l_codec_dpb_ready = false; aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_RESET)", ctx->id, __func__); aml_vdec_reset(ctx); } + mutex_unlock(&ctx->state_lock); + + ctx->is_stream_off = false; } - mutex_unlock(&ctx->state_lock); } - return ret; + return v4l2_m2m_ioctl_streamon(file, priv, i); +} + +static int vidioc_decoder_streamoff(struct file *file, void *priv, + enum v4l2_buf_type i) +{ + struct v4l2_fh *fh = file->private_data; + struct aml_vcodec_ctx *ctx = fh_to_ctx(fh); + struct vb2_queue *q; + + q = v4l2_m2m_get_vq(fh->m2m_ctx, i); + if (!V4L2_TYPE_IS_OUTPUT(q->type)) { + ctx->is_stream_off = true; + } + + return v4l2_m2m_ioctl_streamoff(file, priv, i); } static int vidioc_decoder_reqbufs(struct file *file, void *priv, @@ -964,10 +1096,14 @@ static int vidioc_decoder_reqbufs(struct file *file, void *priv, void aml_vcodec_dec_release(struct aml_vcodec_ctx *ctx) { + ulong flags; + + flags = aml_vcodec_ctx_lock(ctx); ctx->state = AML_STATE_ABORT; - ctx->v4l_codec_ready = false; + ATRACE_COUNTER("v4l2_state", ctx->state); aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ABORT)", ctx->id, __func__); + aml_vcodec_ctx_unlock(ctx, flags); vdec_if_deinit(ctx); } @@ -1016,8 +1152,10 @@ void aml_vcodec_dec_set_default_params(struct aml_vcodec_ctx *ctx) q_data->bytesperline[0] = q_data->coded_width; q_data->sizeimage[1] = q_data->sizeimage[0] / 2; q_data->bytesperline[1] = q_data->coded_width; + ctx->reset_flag = V4L_RESET_MODE_NORMAL; ctx->state = AML_STATE_IDLE; + ATRACE_COUNTER("v4l2_state", ctx->state); aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_IDLE)", ctx->id, __func__); } @@ -1026,6 +1164,7 @@ static int vidioc_vdec_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { struct aml_vcodec_ctx *ctx = fh_to_ctx(priv); + int ret; if (ctx->state == AML_STATE_ABORT) { aml_v4l2_err("[%d] Call on QBUF after unrecoverable error, type = %s", @@ -1034,13 +1173,22 @@ static int vidioc_vdec_qbuf(struct file *file, void *priv, return -EIO; } - return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); + ret = v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); + + if (V4L2_TYPE_IS_OUTPUT(buf->type)) { + if (ret == -EAGAIN) + ATRACE_COUNTER("v4l2_qbuf_eagain", 0); + else + ATRACE_COUNTER("v4l2_qbuf_ok", 0); + } + return ret; } static int vidioc_vdec_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { struct aml_vcodec_ctx *ctx = fh_to_ctx(priv); + int ret; if (ctx->state == AML_STATE_ABORT) { aml_v4l2_err("[%d] Call on DQBUF after unrecoverable error, type = %s", @@ -1050,7 +1198,43 @@ static int vidioc_vdec_dqbuf(struct file *file, void *priv, return -EIO; } - return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); + ret = v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); + if (V4L2_TYPE_IS_OUTPUT(buf->type)) { + if (ret == -EAGAIN) + ATRACE_COUNTER("v4l2_dqin_eagain", 0); + else + ATRACE_COUNTER("v4l2_dqin_ok", 0); + } else if (!V4L2_TYPE_IS_OUTPUT(buf->type)) { + if (ret == -EAGAIN) + ATRACE_COUNTER("v4l2_dqout_eagain", 0); + } + + if (!ret && !V4L2_TYPE_IS_OUTPUT(buf->type)) { + struct vb2_queue *vq; + struct vb2_v4l2_buffer *vb2_v4l2 = NULL; + struct aml_video_dec_buf *aml_buf = NULL; + struct file *file = NULL; + + mutex_lock(&ctx->lock); + vq = v4l2_m2m_get_vq(ctx->m2m_ctx, buf->type); + vb2_v4l2 = to_vb2_v4l2_buffer(vq->bufs[buf->index]); + aml_buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb); + + file = fget(vb2_v4l2->private); + if (is_v4l2_buf_file(file)) { + dmabuf_fd_install_data(vb2_v4l2->private, + (void*)&aml_buf->privdata, + sizeof(struct file_private_data)); + ATRACE_COUNTER("v4l2_dqout_ok", aml_buf->privdata.vf.index_disp); + aml_v4l2_debug(4, "[%d] %s, disp: %d, vf: %p\n", ctx->id, + __func__, aml_buf->privdata.vf.index_disp, + v4l_get_vf_handle(vb2_v4l2->private)); + } + fput(file); + mutex_unlock(&ctx->lock); + } + + return ret; } static int vidioc_vdec_querycap(struct file *file, void *priv, @@ -1312,6 +1496,7 @@ static int vidioc_vdec_s_fmt(struct file *file, void *priv, return -EINVAL; } ctx->state = AML_STATE_INIT; + ATRACE_COUNTER("v4l2_state", ctx->state); aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_INIT)", ctx->id, __func__); } @@ -1366,22 +1551,18 @@ static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, bool output_queue) for (i = 0; i < NUM_FORMATS; i++) { if (output_queue && (aml_video_formats[i].type != AML_FMT_DEC)) continue; - if (!output_queue && - (aml_video_formats[i].type != AML_FMT_FRAME)) + if (!output_queue && (aml_video_formats[i].type != AML_FMT_FRAME)) continue; - if (j == f->index) - break; + if (j == f->index) { + fmt = &aml_video_formats[i]; + f->pixelformat = fmt->fourcc; + return 0; + } ++j; } - if (i == NUM_FORMATS) - return -EINVAL; - - fmt = &aml_video_formats[i]; - f->pixelformat = fmt->fourcc; - - return 0; + return -EINVAL; } static int vidioc_vdec_enum_fmt_vid_cap_mplane(struct file *file, void *pirv, @@ -1584,14 +1765,26 @@ static void vb2ops_vdec_buf_queue(struct vb2_buffer *vb) __func__, __LINE__, buf->frame_buffer.m.mem[0].addr, buf->frame_buffer.vf_handle, buf->frame_buffer.status); - if (!buf->que_in_m2m && buf->frame_buffer.status == FB_ST_NORMAL) { - aml_v4l2_debug(2, "[%d] enque capture buf idx %d, %p", - ctx->id, vb->index, vb); + if (vb->index >= ctx->dpb_size) { + aml_v4l2_debug(2, "[%d] enque capture buf idx %d is invalid.", + ctx->id, vb->index); + return; + } + + if (!buf->que_in_m2m) { + aml_v4l2_debug(2, "[%d] enque capture buf idx %d, vf: %p", + ctx->id, vb->index, v4l_get_vf_handle(vb2_v4l2->private)); + v4l2_m2m_buf_queue(ctx->m2m_ctx, vb2_v4l2); buf->que_in_m2m = true; buf->queued_in_vb2 = true; buf->queued_in_v4l2 = true; buf->ready_to_display = false; + ctx->cap_pool.seq[ctx->cap_pool.in++] = + (V4L_CAP_BUFF_IN_M2M << 16 | vb->index); + + /* check dpb ready */ + aml_check_dpb_ready(ctx); } else if (buf->frame_buffer.status == FB_ST_DISPLAY) { buf->queued_in_vb2 = false; buf->queued_in_v4l2 = true; @@ -1645,11 +1838,12 @@ static void vb2ops_vdec_buf_queue(struct vb2_buffer *vb) ctx->dpb_size = dpb; ctx->last_decoded_picinfo = ctx->picinfo; - aml_vdec_queue_res_chg_event(ctx); + aml_vdec_dispatch_event(ctx, V4L2_EVENT_SRC_CH_RESOLUTION); mutex_lock(&ctx->state_lock); if (ctx->state == AML_STATE_INIT) { ctx->state = AML_STATE_PROBE; + ATRACE_COUNTER("v4l2_state", ctx->state); aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_PROBE)", ctx->id, __func__); } @@ -1675,6 +1869,7 @@ static void vb2ops_vdec_buf_finish(struct vb2_buffer *vb) if (buf_error) { aml_v4l2_err("[%d] Unrecoverable error on buffer.", ctx->id); ctx->state = AML_STATE_ABORT; + ATRACE_COUNTER("v4l2_state", ctx->state); aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ABORT)", ctx->id, __func__); } @@ -1810,21 +2005,26 @@ static void vb2ops_vdec_stop_streaming(struct vb2_queue *q) while ((vb2_v4l2 = v4l2_m2m_src_buf_remove(ctx->m2m_ctx))) v4l2_m2m_buf_done(vb2_v4l2, VB2_BUF_STATE_ERROR); } else { - while ((vb2_v4l2 = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx))) - v4l2_m2m_buf_done(vb2_v4l2, VB2_BUF_STATE_ERROR); + /* stop decoder. */ + wait_vcodec_ending(ctx); for (i = 0; i < q->num_buffers; ++i) { vb2_v4l2 = to_vb2_v4l2_buffer(q->bufs[i]); buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb); buf->frame_buffer.status = FB_ST_NORMAL; buf->que_in_m2m = false; + ctx->cap_pool.seq[i] = 0; + + if (vb2_v4l2->vb2_buf.state == VB2_BUF_STATE_ACTIVE) + v4l2_m2m_buf_done(vb2_v4l2, VB2_BUF_STATE_ERROR); /*pr_info("idx: %d, state: %d\n", q->bufs[i]->index, q->bufs[i]->state);*/ } - - ctx->buf_used_count = 0; } + ctx->buf_used_count = 0; + ctx->cap_pool.in = 0; + ctx->cap_pool.out = 0; } static void m2mops_vdec_device_run(void *priv) @@ -1841,7 +2041,7 @@ void vdec_device_vf_run(struct aml_vcodec_ctx *ctx) { aml_v4l2_debug(3, "[%d] %s() [%d]", ctx->id, __func__, __LINE__); - if (ctx->state < AML_STATE_ACTIVE || + if (ctx->state < AML_STATE_INIT || ctx->state > AML_STATE_FLUSHED) return; @@ -1955,6 +2155,51 @@ err: return ret; } +static int vidioc_vdec_g_parm(struct file *file, void *fh, + struct v4l2_streamparm *a) +{ + struct aml_vcodec_ctx *ctx = fh_to_ctx(fh); + + if (a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { + if (vdec_if_get_param(ctx, GET_PARAM_CONFIG_INFO, + &ctx->config.parm.dec)) { + pr_err("[%d] GET_PARAM_CONFIG_INFO err\n", ctx->id); + return -1; + } + memcpy(a->parm.raw_data, ctx->config.parm.data, + sizeof(a->parm.raw_data)); + } + + return 0; +} + +static int vidioc_vdec_s_parm(struct file *file, void *fh, + struct v4l2_streamparm *a) +{ + struct aml_vcodec_ctx *ctx = fh_to_ctx(fh); + + if (a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { + struct aml_dec_params *in = + (struct aml_dec_params *) a->parm.raw_data; + struct aml_dec_params *dec = &ctx->config.parm.dec; + + ctx->config.type = V4L2_CONFIG_PARM_DECODE; + + if (in->parms_status & V4L2_CONFIG_PARM_DECODE_CFGINFO) + dec->cfg = in->cfg; + if (in->parms_status & V4L2_CONFIG_PARM_DECODE_PSINFO) + dec->ps = in->ps; + if (in->parms_status & V4L2_CONFIG_PARM_DECODE_HDRINFO) + dec->hdr = in->hdr; + if (in->parms_status & V4L2_CONFIG_PARM_DECODE_CNTINFO) + dec->cnt = in->cnt; + + dec->parms_status |= in->parms_status; + } + + return 0; +} + static void m2mops_vdec_lock(void *m2m_priv) { struct aml_vcodec_ctx *ctx = m2m_priv; @@ -1993,7 +2238,7 @@ static const struct vb2_ops aml_vdec_vb2_ops = { const struct v4l2_ioctl_ops aml_vdec_ioctl_ops = { .vidioc_streamon = vidioc_decoder_streamon, - .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, + .vidioc_streamoff = vidioc_decoder_streamoff, .vidioc_reqbufs = vidioc_decoder_reqbufs, .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, .vidioc_expbuf = v4l2_m2m_ioctl_expbuf,//?? @@ -2032,6 +2277,9 @@ const struct v4l2_ioctl_ops aml_vdec_ioctl_ops = { .vidioc_decoder_cmd = vidioc_decoder_cmd, .vidioc_try_decoder_cmd = vidioc_try_decoder_cmd, + + .vidioc_g_parm = vidioc_vdec_g_parm, + .vidioc_s_parm = vidioc_vdec_s_parm, }; int aml_vcodec_dec_queue_init(void *priv, struct vb2_queue *src_vq, diff --git a/drivers/amvdec_ports/aml_vcodec_dec.h b/drivers/amvdec_ports/aml_vcodec_dec.h index 19923c0..68f878a 100644 --- a/drivers/amvdec_ports/aml_vcodec_dec.h +++ b/drivers/amvdec_ports/aml_vcodec_dec.h @@ -23,6 +23,7 @@ #include <media/videobuf2-core.h> #include <media/videobuf2-v4l2.h> #include <linux/amlogic/media/codec_mm/codec_mm.h> +#include <linux/amlogic/media/video_sink/v4lvideo_ext.h> #include "aml_vcodec_util.h" #define VCODEC_CAPABILITY_4K_DISABLED 0x10 @@ -83,6 +84,7 @@ struct aml_video_dec_buf { struct list_head list; struct vdec_v4l2_buffer frame_buffer; + struct file_private_data privdata; struct codec_mm_s *mem[2]; char mem_onwer[32]; bool used; @@ -94,18 +96,9 @@ struct aml_video_dec_buf { bool error; }; -struct aml_vdec_pic_infos { - u32 visible_width; - u32 visible_height; - u32 coded_width; - u32 coded_height; - int dpb_size; -}; - extern const struct v4l2_ioctl_ops aml_vdec_ioctl_ops; extern const struct v4l2_m2m_ops aml_vdec_m2m_ops; - /* * aml_vdec_lock/aml_vdec_unlock are for ctx instance to * get/release lock before/after access decoder hw. @@ -119,9 +112,7 @@ int aml_vcodec_dec_queue_init(void *priv, struct vb2_queue *src_vq, void aml_vcodec_dec_set_default_params(struct aml_vcodec_ctx *ctx); void aml_vcodec_dec_release(struct aml_vcodec_ctx *ctx); int aml_vcodec_dec_ctrls_setup(struct aml_vcodec_ctx *ctx); - void vdec_device_vf_run(struct aml_vcodec_ctx *ctx); - void try_to_capture(struct aml_vcodec_ctx *ctx); void aml_thread_notify(struct aml_vcodec_ctx *ctx, enum aml_thread_type type); @@ -129,5 +120,8 @@ int aml_thread_start(struct aml_vcodec_ctx *ctx, aml_thread_func func, enum aml_thread_type type, const char *thread_name); void aml_thread_stop(struct aml_vcodec_ctx *ctx); void wait_vcodec_ending(struct aml_vcodec_ctx *ctx); +void vdec_frame_buffer_release(void *data); +void aml_vdec_dispatch_event(struct aml_vcodec_ctx *ctx, u32 changes); +void* v4l_get_vf_handle(int fd); #endif /* _AML_VCODEC_DEC_H_ */ diff --git a/drivers/amvdec_ports/aml_vcodec_dec_drv.c b/drivers/amvdec_ports/aml_vcodec_dec_drv.c index a50f9b1..43ff0c5 100644 --- a/drivers/amvdec_ports/aml_vcodec_dec_drv.c +++ b/drivers/amvdec_ports/aml_vcodec_dec_drv.c @@ -35,12 +35,20 @@ #include "aml_vcodec_dec_pm.h" #include "aml_vcodec_util.h" #include "aml_vcodec_vfm.h" +#include <linux/file.h> +#include <linux/anon_inodes.h> #define VDEC_HW_ACTIVE 0x10 #define VDEC_IRQ_CFG 0x11 #define VDEC_IRQ_CLR 0x10 #define VDEC_IRQ_CFG_REG 0xa4 +#define V4LVIDEO_IOC_MAGIC 'I' +#define V4LVIDEO_IOCTL_ALLOC_FD _IOW(V4LVIDEO_IOC_MAGIC, 0x02, int) +#define V4LVIDEO_IOCTL_CHECK_FD _IOW(V4LVIDEO_IOC_MAGIC, 0x03, int) +#define V4LVIDEO_IOCTL_SET_CONFIG_PARAMS _IOWR(V4LVIDEO_IOC_MAGIC, 0x04, struct v4l2_config_parm) +#define V4LVIDEO_IOCTL_GET_CONFIG_PARAMS _IOWR(V4LVIDEO_IOC_MAGIC, 0x05, struct v4l2_config_parm) + bool scatter_mem_enable; bool param_sets_from_ucode; @@ -68,7 +76,6 @@ static int fops_vcodec_open(struct file *file) file->private_data = &ctx->fh; v4l2_fh_add(&ctx->fh); INIT_LIST_HEAD(&ctx->list); - INIT_LIST_HEAD(&ctx->capture_list); INIT_LIST_HEAD(&ctx->vdec_thread_list); dev->filp = file; ctx->dev = dev; @@ -159,12 +166,227 @@ static int fops_vcodec_release(struct file *file) return 0; } +static int v4l2video_file_release(struct inode *inode, struct file *file) +{ + aml_v4l2_debug(2,"%s: file: 0x%p, data: %p", + __func__, file, file->private_data); + + if (file->private_data) + vdec_frame_buffer_release(file->private_data); + + return 0; +} + +const struct file_operations v4l2_file_fops = { + .release = v4l2video_file_release, +}; + +int v4l2_alloc_fd(int *fd) +{ + struct file *file = NULL; + int file_fd = get_unused_fd_flags(O_CLOEXEC); + + if (file_fd < 0) { + pr_err("%s: get unused fd fail\n", __func__); + return -ENODEV; + } + + file = anon_inode_getfile("v4l2_meta_file", &v4l2_file_fops, NULL, 0); + if (IS_ERR(file)) { + put_unused_fd(file_fd); + pr_err("%s: anon_inode_getfile fail\n", __func__); + return -ENODEV; + } + + file->private_data = + kzalloc(sizeof(struct file_private_data), GFP_KERNEL); + if (!file->private_data) { + pr_err("%s: alloc priv data faild.\n", __func__); + return -ENOMEM; + } + + aml_v4l2_debug(2, "%s: fd %d, file %p", __func__, file_fd, file); + + fd_install(file_fd, file); + *fd = file_fd; + + return 0; +} + +extern const struct file_operations v4l2_file_fops; +bool is_v4l2_buf_file(struct file *file) +{ + return file->f_op == &v4l2_file_fops; +} + +int v4l2_check_fd(int fd) +{ + struct file *file; + + file = fget(fd); + + if (!file) { + pr_err("%s: fget fd %d fail!\n", __func__, fd); + return -EBADF; + } + + if (!is_v4l2_buf_file(file)) { + fput(file); + pr_err("%s: is_v4l2_buf_file fail!\n", __func__); + return -1; + } + + fput(file); + + aml_v4l2_debug(5, "%s: ioctl ok, comm %s, pid %d", + __func__, current->comm, current->pid); + + return 0; +} + +int dmabuf_fd_install_data(int fd, void* data, u32 size) +{ + struct file *file; + + file = fget(fd); + + if (!file) { + pr_err("%s: fget fd %d fail!, comm %s, pid %d\n", + __func__, fd, current->comm, current->pid); + return -EBADF; + } + + if (!is_v4l2_buf_file(file)) { + fput(file); + pr_err("%s the buf file checked fail!\n", __func__); + return -EBADF; + } + + memcpy(file->private_data, data, size); + + fput(file); + + return 0; +} + +void* v4l_get_vf_handle(int fd) +{ + struct file *file; + struct file_private_data *data = NULL; + void *vf_handle = 0; + + file = fget(fd); + + if (!file) { + pr_err("%s: fget fd %d fail!, comm %s, pid %d\n", + __func__, fd, current->comm, current->pid); + return NULL; + } + + if (!is_v4l2_buf_file(file)) { + fput(file); + pr_err("%s the buf file checked fail!\n", __func__); + return NULL; + } + + data = (struct file_private_data*) file->private_data; + if (data) + vf_handle = &data->vf; + + fput(file); + + return vf_handle; +} + + +static long v4l2_vcodec_ioctl(struct file *file, + unsigned int cmd, + ulong arg) +{ + long ret = 0; + void __user *argp = (void __user *)arg; + + switch (cmd) { + case V4LVIDEO_IOCTL_ALLOC_FD: + { + u32 v4lvideo_fd = 0; + + ret = v4l2_alloc_fd(&v4lvideo_fd); + if (ret != 0) + break; + put_user(v4lvideo_fd, (u32 __user *)argp); + aml_v4l2_debug(4, "%s: V4LVIDEO_IOCTL_ALLOC_FD fd %d", + __func__, v4lvideo_fd); + break; + } + case V4LVIDEO_IOCTL_CHECK_FD: + { + u32 v4lvideo_fd = 0; + + get_user(v4lvideo_fd, (u32 __user *)argp); + ret = v4l2_check_fd(v4lvideo_fd); + if (ret != 0) + break; + aml_v4l2_debug(4, "%s: V4LVIDEO_IOCTL_CHECK_FD fd %d", + __func__, v4lvideo_fd); + break; + } + case V4LVIDEO_IOCTL_SET_CONFIG_PARAMS: + { + struct aml_vcodec_ctx *ctx = NULL; + + if (is_v4l2_buf_file(file)) + break; + + ctx = fh_to_ctx(file->private_data); + if (copy_from_user((void *)&ctx->config, + (void *)argp, sizeof(ctx->config))) { + pr_err("[%s],set config parm err\n", __func__); + return -EFAULT; + } + break; + } + case V4LVIDEO_IOCTL_GET_CONFIG_PARAMS: + { + struct aml_vcodec_ctx *ctx = NULL; + + if (is_v4l2_buf_file(file)) + break; + + ctx = fh_to_ctx(file->private_data); + if (copy_to_user((void *)argp, + (void *)&ctx->config, sizeof(ctx->config))) { + pr_err("[%s],get config parm err\n", __func__); + return -EFAULT; + } + break; + } + default: + return video_ioctl2(file, cmd, arg); + } + return ret; +} + +#ifdef CONFIG_COMPAT +static long v4l2_compat_ioctl(struct file *file, + unsigned int cmd, ulong arg) +{ + long ret = 0; + + ret = v4l2_vcodec_ioctl(file, cmd, (ulong)compat_ptr(arg)); + return ret; +} +#endif + static const struct v4l2_file_operations aml_vcodec_fops = { .owner = THIS_MODULE, .open = fops_vcodec_open, .release = fops_vcodec_release, .poll = v4l2_m2m_fop_poll, - .unlocked_ioctl = video_ioctl2, + .unlocked_ioctl = v4l2_vcodec_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl32 = v4l2_compat_ioctl, +#endif .mmap = v4l2_m2m_fop_mmap, }; diff --git a/drivers/amvdec_ports/aml_vcodec_drv.h b/drivers/amvdec_ports/aml_vcodec_drv.h index a7c9aaf..1baec44 100644 --- a/drivers/amvdec_ports/aml_vcodec_drv.h +++ b/drivers/amvdec_ports/aml_vcodec_drv.h @@ -26,6 +26,7 @@ #include <media/v4l2-device.h> #include <media/v4l2-ioctl.h> #include <media/videobuf2-core.h> +#include <linux/amlogic/media/vfm/vframe.h> #include "aml_vcodec_util.h" #define AML_VCODEC_DRV_NAME "aml_vcodec_drv" @@ -37,6 +38,36 @@ #define AML_V4L2_BENCHMARK 0 #define WAIT_INTR_TIMEOUT_MS 1000 +/* codec types of get/set parms. */ +#define V4L2_CONFIG_PARM_ENCODE (0) +#define V4L2_CONFIG_PARM_DECODE (1) + +/* types of decode parms. */ +#define V4L2_CONFIG_PARM_DECODE_CFGINFO (1 << 0) +#define V4L2_CONFIG_PARM_DECODE_PSINFO (1 << 1) +#define V4L2_CONFIG_PARM_DECODE_HDRINFO (1 << 2) +#define V4L2_CONFIG_PARM_DECODE_CNTINFO (1 << 3) + +/* amlogic event define. */ +/* #define V4L2_EVENT_SRC_CH_RESOLUTION (1 << 0) */ +#define V4L2_EVENT_SRC_CH_HDRINFO (1 << 1) +#define V4L2_EVENT_SRC_CH_PSINFO (1 << 2) +#define V4L2_EVENT_SRC_CH_CNTINFO (1 << 3) + +/* exception handing */ +#define V4L2_EVENT_REQUEST_RESET (1 << 8) +#define V4L2_EVENT_REQUEST_EXIT (1 << 9) + +/* v4l buffer pool */ +#define V4L_CAP_BUFF_MAX (32) +#define V4L_CAP_BUFF_INVALID (0) +#define V4L_CAP_BUFF_IN_M2M (1) +#define V4L_CAP_BUFF_IN_DEC (2) + +/* v4l reset mode */ +#define V4L_RESET_MODE_NORMAL (1 << 0) /* reset vdec_input and decoder. */ +#define V4L_RESET_MODE_LIGHT (1 << 1) /* just only reset decoder. */ + /** * enum aml_hw_reg_idx - AML hw register base index */ @@ -136,6 +167,7 @@ enum aml_q_type { AML_Q_DATA_DST = 1, }; + /** * struct aml_q_data - Structure used to store information about queue */ @@ -233,6 +265,86 @@ struct vdec_pic_info { unsigned int c_bs_sz; unsigned int y_len_sz; unsigned int c_len_sz; + int profile_idc; +}; + +struct aml_vdec_cfg_infos { + u32 double_write_mode; + u32 init_width; + u32 init_height; + u32 ref_buf_margin; + u32 canvas_mem_mode; + u32 canvas_mem_endian; +}; + +struct aml_vdec_hdr_infos { + /* + * bit 29 : present_flag + * bit 28-26: video_format "component", "PAL", "NTSC", "SECAM", "MAC", "unspecified" + * bit 25 : range "limited", "full_range" + * bit 24 : color_description_present_flag + * bit 23-16: color_primaries "unknown", "bt709", "undef", "bt601", + * "bt470m", "bt470bg", "smpte170m", "smpte240m", "film", "bt2020" + * bit 15-8 : transfer_characteristic unknown", "bt709", "undef", "bt601", + * "bt470m", "bt470bg", "smpte170m", "smpte240m", + * "linear", "log100", "log316", "iec61966-2-4", + * "bt1361e", "iec61966-2-1", "bt2020-10", "bt2020-12", + * "smpte-st-2084", "smpte-st-428" + * bit 7-0 : matrix_coefficient "GBR", "bt709", "undef", "bt601", + * "fcc", "bt470bg", "smpte170m", "smpte240m", + * "YCgCo", "bt2020nc", "bt2020c" + */ + u32 signal_type; + struct vframe_master_display_colour_s color_parms; +}; + +struct aml_vdec_ps_infos { + u32 visible_width; + u32 visible_height; + u32 coded_width; + u32 coded_height; + u32 profile; + u32 mb_width; + u32 mb_height; + u32 dpb_size; + u32 ref_frames; + u32 reorder_frames; +}; + +struct aml_vdec_cnt_infos { + u32 bit_rate; + u32 frame_count; + u32 error_frame_count; + u32 drop_frame_count; + u32 total_data; +}; + +struct aml_dec_params { + u32 parms_status; + struct aml_vdec_cfg_infos cfg; + struct aml_vdec_ps_infos ps; + struct aml_vdec_hdr_infos hdr; + struct aml_vdec_cnt_infos cnt; +}; + +struct v4l2_config_parm { + u32 type; + u32 length; + union { + struct aml_dec_params dec; + struct aml_enc_params enc; + u8 data[200]; + } parm; + u8 buf[4096]; +}; + +struct v4l_buff_pool { + /* + * bit 31-16: buffer state + * bit 15- 0: buffer index + */ + u32 seq[V4L_CAP_BUFF_MAX]; + u32 in, out; }; enum aml_thread_type { @@ -335,7 +447,6 @@ struct aml_vcodec_ctx { struct mutex lock; struct completion comp; bool has_receive_eos; - struct list_head capture_list; struct list_head vdec_thread_list; bool is_drm_mode; bool is_stream_mode; @@ -344,8 +455,15 @@ struct aml_vcodec_ctx { bool scatter_mem_enable; bool param_sets_from_ucode; bool v4l_codec_ready; + bool v4l_codec_dpb_ready; wait_queue_head_t wq; spinlock_t slock; + struct v4l2_config_parm config; + bool is_stream_off; + int reset_flag; + int stop_cmd; + u32 display_count; + struct v4l_buff_pool cap_pool; }; /** diff --git a/drivers/amvdec_ports/aml_vcodec_vfm.c b/drivers/amvdec_ports/aml_vcodec_vfm.c index e7b85fb..b64be0c 100644 --- a/drivers/amvdec_ports/aml_vcodec_vfm.c +++ b/drivers/amvdec_ports/aml_vcodec_vfm.c @@ -23,6 +23,9 @@ #include "aml_vcodec_adapt.h" #include <media/v4l2-mem2mem.h> +#define KERNEL_ATRACE_TAG KERNEL_ATRACE_TAG_VIDEO_COMPOSER +#include <trace/events/meson_atrace.h> + #define RECEIVER_NAME "v4l2-video" #define PROVIDER_NAME "v4l2-video" @@ -94,6 +97,7 @@ void video_vf_put(char *receiver, struct vdec_v4l2_buffer *fb, int id) aml_v4l2_debug(3, "[%d] TO (%s) vf: %p, idx: %d", id, vfp->name, vf, vf->index); + ATRACE_COUNTER("v4l2_to", vf->index_disp); aml_v4l2_debug(4, "[%d] TO Y:(%lx, %u) C/U:(%lx, %u) V:(%lx, %u)", id, fb->m.mem[0].addr, fb->m.mem[0].size, @@ -214,6 +218,8 @@ struct vframe_s *get_video_frame(struct vcodec_vfm_s *vfm) int vcodec_vfm_init(struct vcodec_vfm_s *vfm) { + int ret; + snprintf(vfm->recv_name, VF_NAME_SIZE, "%s-%d", RECEIVER_NAME, vfm->ctx->id); snprintf(vfm->prov_name, VF_NAME_SIZE, "%s-%d", @@ -222,13 +228,16 @@ int vcodec_vfm_init(struct vcodec_vfm_s *vfm) vfm->ada_ctx->recv_name = vfm->recv_name; vf_receiver_init(&vfm->vf_recv, vfm->recv_name, &vf_receiver, vfm); - vf_reg_receiver(&vfm->vf_recv); + ret = vf_reg_receiver(&vfm->vf_recv); - return 0; + vfm->vfm_initialized = ret ? false : true; + + return ret; } void vcodec_vfm_release(struct vcodec_vfm_s *vfm) { - vf_unreg_receiver(&vfm->vf_recv); + if (vfm->vfm_initialized) + vf_unreg_receiver(&vfm->vf_recv); } diff --git a/drivers/amvdec_ports/aml_vcodec_vfm.h b/drivers/amvdec_ports/aml_vcodec_vfm.h index 9aaf266..141e9a7 100644 --- a/drivers/amvdec_ports/aml_vcodec_vfm.h +++ b/drivers/amvdec_ports/aml_vcodec_vfm.h @@ -41,6 +41,7 @@ struct vcodec_vfm_s { char prov_name[VF_NAME_SIZE]; struct vframe_provider_s vf_prov; struct vframe_receiver_s vf_recv; + bool vfm_initialized; }; int vcodec_vfm_init(struct vcodec_vfm_s *vfm); diff --git a/drivers/amvdec_ports/decoder/aml_h264_parser.c b/drivers/amvdec_ports/decoder/aml_h264_parser.c index cf4e0e8..602633b 100644 --- a/drivers/amvdec_ports/decoder/aml_h264_parser.c +++ b/drivers/amvdec_ports/decoder/aml_h264_parser.c @@ -100,10 +100,10 @@ static int decode_scaling_list(struct get_bits_context *gb, for (i = 0; i < size; i++) { if (next) { int v = get_se_golomb(gb); - if (v < -128 || v > 127) { + /*if (v < -128 || v > 127) { //JM19 has not check. pr_err( "delta scale %d is invalid\n", v); return -1; - } + }*/ next = (last + v) & 0xff; } if (!i && !next) { /* matrix not written, we use the preset one */ @@ -495,6 +495,7 @@ static int aml_h264_parser_sps(struct get_bits_context *gb, struct h264_SPS_t *s goto out; } +#if 0 /* if the maximum delay is not stored in the SPS, derive it based on the level */ if (!sps->bitstream_restriction_flag && sps->ref_frame_count) { sps->num_reorder_frames = MAX_DELAYED_PIC_COUNT - 1; @@ -507,6 +508,28 @@ static int aml_h264_parser_sps(struct get_bits_context *gb, struct h264_SPS_t *s } } } +#endif + + sps->num_reorder_frames = MAX_DELAYED_PIC_COUNT - 1; + for (i = 0; i < ARRAY_SIZE(level_max_dpb_mbs); i++) { + if (level_max_dpb_mbs[i][0] == sps->level_idc) { + sps->num_reorder_frames = + MIN(level_max_dpb_mbs[i][1] / (sps->mb_width * sps->mb_height), + sps->num_reorder_frames); + sps->num_reorder_frames += 1; + if (sps->max_dec_frame_buffering > sps->num_reorder_frames) + sps->num_reorder_frames = sps->max_dec_frame_buffering; + break; + } + } + + if ((sps->bitstream_restriction_flag) && + (sps->max_dec_frame_buffering < + sps->num_reorder_frames)) { + sps->num_reorder_frames = sps->max_dec_frame_buffering; + pr_info("set reorder_pic_num to %d\n", + sps->num_reorder_frames); + } if (!sps->sar.den) sps->sar.den = 1; @@ -601,6 +624,7 @@ static int decode_extradata_ps(u8 *data, int size, struct h264_param_sets *ps) goto out; if (get_bits1(&gb) != 0) { + ret = -1; pr_err("invalid h264 data,return!\n"); goto out; } @@ -651,6 +675,10 @@ int h264_decode_extradata_ps(u8 *buf, int size, struct h264_param_sets *ps) pr_err("parse extra data failed. err: %d\n", ret); return ret; } + + if (ps->sps_parsed) + break; + p += j; } p++; diff --git a/drivers/amvdec_ports/decoder/aml_hevc_parser.c b/drivers/amvdec_ports/decoder/aml_hevc_parser.c index 33d44f1..03b8356 100644 --- a/drivers/amvdec_ports/decoder/aml_hevc_parser.c +++ b/drivers/amvdec_ports/decoder/aml_hevc_parser.c @@ -1204,6 +1204,7 @@ static int decode_extradata_ps(u8 *data, int size, struct h265_param_sets *ps) goto out; if (get_bits1(&gb) != 0) { + ret = -1; pr_err("invalid data, return!\n"); goto out; } @@ -1211,8 +1212,10 @@ static int decode_extradata_ps(u8 *data, int size, struct h265_param_sets *ps) nal_type = get_bits(&gb, 6); nuh_layer_id = get_bits(&gb, 6); temporal_id = get_bits(&gb, 3) - 1; - if (temporal_id < 0) + if (temporal_id < 0) { + ret = -1; goto out; + } /*pr_info("nal_unit_type: %d(%s), nuh_layer_id: %d, temporal_id: %d\n", nal_type, hevc_nal_unit_name(nal_type), @@ -1246,7 +1249,7 @@ static int decode_extradata_ps(u8 *data, int size, struct h265_param_sets *ps) out: vfree(rbsp_buf); - return 0; + return ret; } int h265_decode_extradata_ps(u8 *buf, int size, struct h265_param_sets *ps) @@ -1264,6 +1267,10 @@ int h265_decode_extradata_ps(u8 *buf, int size, struct h265_param_sets *ps) pr_err("parse extra data failed. err: %d\n", ret); return ret; } + + if (ps->sps_parsed) + break; + p += j; } p++; diff --git a/drivers/amvdec_ports/decoder/vdec_h264_if.c b/drivers/amvdec_ports/decoder/vdec_h264_if.c index 02848b8..eada4ea 100644 --- a/drivers/amvdec_ports/decoder/vdec_h264_if.c +++ b/drivers/amvdec_ports/decoder/vdec_h264_if.c @@ -27,6 +27,7 @@ #include "../vdec_drv_if.h" #include "../aml_vcodec_util.h" #include "../aml_vcodec_dec.h" +#include "../aml_vcodec_drv.h" #include "../aml_vcodec_adapt.h" #include "../vdec_drv_base.h" #include "../aml_vcodec_vfm.h" @@ -150,6 +151,7 @@ struct vdec_h264_inst { struct aml_vdec_adapt vdec; struct vdec_h264_vsi *vsi; struct vcodec_vfm_s vfm; + struct aml_dec_params parms; struct completion comp; }; @@ -244,6 +246,48 @@ static void skip_aud_data(u8 **data, u32 *size) } } +static u32 vdec_config_default_parms(u8 *parm) +{ + u8 *pbuf = parm; + + pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;"); + pbuf += sprintf(pbuf, "mh264_double_write_mode:16;"); + pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:7;"); + pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_mode:0;"); + pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_endian:0;"); + + return parm - pbuf; +} + +static void vdec_parser_parms(struct vdec_h264_inst *inst) +{ + struct aml_vcodec_ctx *ctx = inst->ctx; + + if (ctx->config.parm.dec.parms_status & + V4L2_CONFIG_PARM_DECODE_CFGINFO) { + u8 *pbuf = ctx->config.buf; + + pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;"); + pbuf += sprintf(pbuf, "mh264_double_write_mode:%d;", + ctx->config.parm.dec.cfg.double_write_mode); + pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:%d;", + ctx->config.parm.dec.cfg.ref_buf_margin); + pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_mode:%d;", + ctx->config.parm.dec.cfg.canvas_mem_mode); + pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_endian:%d;", + ctx->config.parm.dec.cfg.canvas_mem_endian); + ctx->config.length = pbuf - ctx->config.buf; + } else { + ctx->config.parm.dec.cfg.double_write_mode = 16; + ctx->config.parm.dec.cfg.ref_buf_margin = 7; + ctx->config.length = vdec_config_default_parms(ctx->config.buf); + } + + inst->vdec.config = ctx->config; + inst->parms.cfg = ctx->config.parm.dec.cfg; + inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_CFGINFO; +} + static int vdec_h264_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) { struct vdec_h264_inst *inst = NULL; @@ -253,66 +297,66 @@ static int vdec_h264_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) if (!inst) return -ENOMEM; - inst->ctx = ctx; + inst->vdec.video_type = VFORMAT_H264; + inst->vdec.dev = ctx->dev->vpu_plat_dev; + inst->vdec.filp = ctx->dev->filp; + inst->vdec.ctx = ctx; + inst->ctx = ctx; - inst->vdec.video_type = VFORMAT_H264; - inst->vdec.dev = ctx->dev->vpu_plat_dev; - inst->vdec.filp = ctx->dev->filp; - inst->vdec.ctx = ctx; + vdec_parser_parms(inst); /* set play mode.*/ if (ctx->is_drm_mode) inst->vdec.port.flag |= PORT_FLAG_DRM; /* init vfm */ - inst->vfm.ctx = ctx; - inst->vfm.ada_ctx = &inst->vdec; - vcodec_vfm_init(&inst->vfm); + inst->vfm.ctx = ctx; + inst->vfm.ada_ctx = &inst->vdec; + ret = vcodec_vfm_init(&inst->vfm); + if (ret) { + pr_err("%s, init vfm failed.\n", __func__); + goto err; + } ret = video_decoder_init(&inst->vdec); if (ret) { aml_vcodec_err(inst, "vdec_h264 init err=%d", ret); - goto error_free_inst; + goto err; } /* probe info from the stream */ inst->vsi = kzalloc(sizeof(struct vdec_h264_vsi), GFP_KERNEL); if (!inst->vsi) { ret = -ENOMEM; - goto error_free_inst; + goto err; } /* alloc the header buffer to be used cache sps or spp etc.*/ inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL); if (!inst->vsi) { ret = -ENOMEM; - goto error_free_vsi; + goto err; } - inst->vsi->pic.visible_width = 1920; - inst->vsi->pic.visible_height = 1080; - inst->vsi->pic.coded_width = 1920; - inst->vsi->pic.coded_height = 1088; - inst->vsi->pic.y_bs_sz = 0; - inst->vsi->pic.y_len_sz = (1920 * 1088); - inst->vsi->pic.c_bs_sz = 0; - inst->vsi->pic.c_len_sz = (1920 * 1088 / 2); - init_completion(&inst->comp); aml_vcodec_debug(inst, "H264 Instance >> %p", inst); - ctx->ada_ctx = &inst->vdec; - *h_vdec = (unsigned long)inst; + ctx->ada_ctx = &inst->vdec; + *h_vdec = (unsigned long)inst; //dump_init(); return 0; - -error_free_vsi: - kfree(inst->vsi); -error_free_inst: - kfree(inst); +err: + if (inst) + vcodec_vfm_release(&inst->vfm); + if (inst && inst->vsi && inst->vsi->header_buf) + kfree(inst->vsi->header_buf); + if (inst && inst->vsi) + kfree(inst->vsi); + if (inst) + kfree(inst); *h_vdec = 0; return ret; @@ -388,11 +432,32 @@ static int refer_buffer_num(int level_idc, int max_poc_cnt, } #endif +static void vdec_config_dw_mode(struct vdec_pic_info *pic, int dw_mode) +{ + switch (dw_mode) { + case 0x1: /* (w x h) + (w/2 x h) */ + pic->coded_width += pic->coded_width >> 1; + pic->y_len_sz = pic->coded_width * pic->coded_height; + pic->c_len_sz = pic->y_len_sz >> 1; + break; + case 0x2: /* (w x h) + (w/2 x h/2) */ + pic->coded_width += pic->coded_width >> 1; + pic->coded_height += pic->coded_height >> 1; + pic->y_len_sz = pic->coded_width * pic->coded_height; + pic->c_len_sz = pic->y_len_sz >> 1; + break; + default: /* nothing to do */ + break; + } +} + static void fill_vdec_params(struct vdec_h264_inst *inst, struct h264_SPS_t *sps) { struct vdec_pic_info *pic = &inst->vsi->pic; struct vdec_h264_dec_info *dec = &inst->vsi->dec; struct v4l2_rect *rect = &inst->vsi->crop; + int dw = inst->parms.cfg.double_write_mode; + int margin = inst->parms.cfg.ref_buf_margin; u32 mb_w, mb_h, width, height; mb_w = sps->mb_width; @@ -419,13 +484,29 @@ static void fill_vdec_params(struct vdec_h264_inst *inst, struct h264_SPS_t *sps pic->coded_height = ALIGN(mb_h, 4) << 4; pic->y_len_sz = pic->coded_width * pic->coded_height; pic->c_len_sz = pic->y_len_sz >> 1; + pic->profile_idc = sps->profile_idc; /* calc DPB size */ - dec->dpb_sz = sps->ref_frame_count; - - aml_vcodec_debug(inst, "[%d] The stream infos, coded:(%d x %d), visible:(%d x %d), DPB: %d\n", - inst->ctx->id, pic->coded_width, pic->coded_height, - pic->visible_width, pic->visible_height, dec->dpb_sz); + dec->dpb_sz = sps->num_reorder_frames + margin; + + inst->parms.ps.visible_width = pic->visible_width; + inst->parms.ps.visible_height = pic->visible_height; + inst->parms.ps.coded_width = pic->coded_width; + inst->parms.ps.coded_height = pic->coded_height; + inst->parms.ps.profile = sps->profile_idc; + inst->parms.ps.mb_width = sps->mb_width; + inst->parms.ps.mb_height = sps->mb_height; + inst->parms.ps.ref_frames = sps->ref_frame_count; + inst->parms.ps.reorder_frames = sps->num_reorder_frames; + inst->parms.ps.dpb_size = dec->dpb_sz; + inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_PSINFO; + + vdec_config_dw_mode(pic, dw); + + aml_vcodec_debug(inst, "[%d] The stream infos, dw: %d, coded:(%d x %d), visible:(%d x %d), DPB: %d, margin: %d\n", + inst->ctx->id, dw, pic->coded_width, pic->coded_height, + pic->visible_width, pic->visible_height, + dec->dpb_sz - margin, margin); } static bool check_frame_combine(u8 *buf, u32 size, int *pos) @@ -453,6 +534,24 @@ static bool check_frame_combine(u8 *buf, u32 size, int *pos) return combine; } +static int vdec_search_startcode(u8 *buf, u32 range) +{ + int pos = -1; + int i = 0, j = 0; + u8 *p = buf; + + for (i = 4; i < range; i++) { + j = find_start_code(p, 7); + if (j > 0) { + pos = p - buf + j; + break; + } + p++; + } + + return pos; +} + static int stream_parse_by_ucode(struct vdec_h264_inst *inst, u8 *buf, u32 size) { int ret = 0; @@ -475,7 +574,6 @@ static int stream_parse(struct vdec_h264_inst *inst, u8 *buf, u32 size) { int ret = 0; struct h264_param_sets *ps; - u32 nal_type; int nal_idx = 0; bool is_combine = false; @@ -483,15 +581,11 @@ static int stream_parse(struct vdec_h264_inst *inst, u8 *buf, u32 size) if (nal_idx < 0) return -1; - nal_type = AVC_NAL_TYPE(buf[nal_idx]); - if (nal_type != NAL_H264_SPS) - return -1; - /* if the st compose from csd + slice that is the combine data. */ inst->vsi->is_combine = is_combine; inst->vsi->nalu_pos = nal_idx; - ps = kzalloc(sizeof(struct h264_param_sets), GFP_KERNEL); + ps = vzalloc(sizeof(struct h264_param_sets)); if (ps == NULL) return -ENOMEM; @@ -506,7 +600,7 @@ static int stream_parse(struct vdec_h264_inst *inst, u8 *buf, u32 size) ret = ps->sps_parsed ? 0 : -1; out: - kfree(ps); + vfree(ps); return ret; } @@ -618,7 +712,9 @@ static int vdec_write_nalu(struct vdec_h264_inst *inst, int nalu_pos; u32 nal_type; - nalu_pos = find_start_code(buf, size); + /*print_hex_debug(buf, size, 32);*/ + + nalu_pos = vdec_search_startcode(buf, 16); if (nalu_pos < 0) goto err; @@ -701,19 +797,25 @@ static bool monitor_res_change(struct vdec_h264_inst *inst, u8 *buf, u32 size) if (type == NAL_H264_SPS) { ret = stream_parse(inst, p, len); - if (!ret && (inst->vsi->cur_pic.coded_width != - inst->vsi->pic.coded_width || - inst->vsi->cur_pic.coded_height != - inst->vsi->pic.coded_height)) { - inst->vsi->cur_pic = inst->vsi->pic; - return true; - } + if (ret) + break; } p += j; } p++; } + if (!ret && ((inst->vsi->cur_pic.coded_width != + inst->vsi->pic.coded_width || + inst->vsi->cur_pic.coded_height != + inst->vsi->pic.coded_height) || + (inst->vsi->pic.profile_idc != + inst->vsi->cur_pic.profile_idc))) { + pr_info("res change\n"); + inst->vsi->cur_pic = inst->vsi->pic; + return true; + } + return false; } @@ -727,10 +829,12 @@ static int vdec_h264_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs, u32 size; int ret = -1; - /* bs NULL means flush decoder */ if (bs == NULL) return -1; + if (vdec_input_full(vdec)) + return -EAGAIN; + buf = (u8 *)bs->vaddr; size = bs->size; st = (struct stream_info *)buf; @@ -754,6 +858,23 @@ static int vdec_h264_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs, return ret; } +static void get_param_config_info(struct vdec_h264_inst *inst, + struct aml_dec_params *parms) +{ + if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_CFGINFO) + parms->cfg = inst->parms.cfg; + if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_PSINFO) + parms->ps = inst->parms.ps; + if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_HDRINFO) + parms->hdr = inst->parms.hdr; + if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_CNTINFO) + parms->cnt = inst->parms.cnt; + + parms->parms_status |= inst->parms.parms_status; + + aml_vcodec_debug(inst, "parms status: %u", parms->parms_status); +} + static int vdec_h264_get_param(unsigned long h_vdec, enum vdec_get_param_type type, void *out) { @@ -786,6 +907,9 @@ static int vdec_h264_get_param(unsigned long h_vdec, get_crop_info(inst, out); break; + case GET_PARAM_CONFIG_INFO: + get_param_config_info(inst, out); + break; default: aml_vcodec_err(inst, "invalid get parameter type=%d", type); ret = -EINVAL; @@ -799,16 +923,16 @@ static void set_param_write_sync(struct vdec_h264_inst *inst) complete(&inst->comp); } -static void set_param_pic_info(struct vdec_h264_inst *inst, - struct aml_vdec_pic_infos *info) +static void set_param_ps_info(struct vdec_h264_inst *inst, + struct aml_vdec_ps_infos *ps) { struct vdec_pic_info *pic = &inst->vsi->pic; struct vdec_h264_dec_info *dec = &inst->vsi->dec; struct v4l2_rect *rect = &inst->vsi->crop; /* fill visible area size that be used for EGL. */ - pic->visible_width = info->visible_width; - pic->visible_height = info->visible_height; + pic->visible_width = ps->visible_width; + pic->visible_height = ps->visible_height; /* calc visible ares. */ rect->left = 0; @@ -817,20 +941,45 @@ static void set_param_pic_info(struct vdec_h264_inst *inst, rect->height = pic->visible_height; /* config canvas size that be used for decoder. */ - pic->coded_width = info->coded_width; - pic->coded_height = info->coded_height; + pic->coded_width = ps->coded_width; + pic->coded_height = ps->coded_height; pic->y_len_sz = pic->coded_width * pic->coded_height; pic->c_len_sz = pic->y_len_sz >> 1; - dec->dpb_sz = info->dpb_size; + dec->dpb_sz = ps->dpb_size; + + inst->parms.ps = *ps; + inst->parms.parms_status |= + V4L2_CONFIG_PARM_DECODE_PSINFO; /*wake up*/ complete(&inst->comp); pr_info("Parse from ucode, crop(%d x %d), coded(%d x %d) dpb: %d\n", - info->visible_width, info->visible_height, - info->coded_width, info->coded_height, - info->dpb_size); + ps->visible_width, ps->visible_height, + ps->coded_width, ps->coded_height, + dec->dpb_sz); +} + +static void set_param_hdr_info(struct vdec_h264_inst *inst, + struct aml_vdec_hdr_infos *hdr) +{ + inst->parms.hdr = *hdr; + if (!(inst->parms.parms_status & + V4L2_CONFIG_PARM_DECODE_HDRINFO)) { + inst->parms.hdr = *hdr; + inst->parms.parms_status |= + V4L2_CONFIG_PARM_DECODE_HDRINFO; + aml_vdec_dispatch_event(inst->ctx, + V4L2_EVENT_SRC_CH_HDRINFO); + pr_info("H264 set HDR infos\n"); + } +} + +static void set_param_post_event(struct vdec_h264_inst *inst, u32 *event) +{ + aml_vdec_dispatch_event(inst->ctx, *event); + pr_info("H264 post event: %d\n", *event); } static int vdec_h264_set_param(unsigned long h_vdec, @@ -849,10 +998,17 @@ static int vdec_h264_set_param(unsigned long h_vdec, set_param_write_sync(inst); break; - case SET_PARAM_PIC_INFO: - set_param_pic_info(inst, in); + case SET_PARAM_PS_INFO: + set_param_ps_info(inst, in); + break; + + case SET_PARAM_HDR_INFO: + set_param_hdr_info(inst, in); break; + case SET_PARAM_POST_EVENT: + set_param_post_event(inst, in); + break; default: aml_vcodec_err(inst, "invalid set parameter type=%d", type); ret = -EINVAL; diff --git a/drivers/amvdec_ports/decoder/vdec_hevc_if.c b/drivers/amvdec_ports/decoder/vdec_hevc_if.c index 59ce85f..cd4d361 100644 --- a/drivers/amvdec_ports/decoder/vdec_hevc_if.c +++ b/drivers/amvdec_ports/decoder/vdec_hevc_if.c @@ -26,6 +26,7 @@ #include "../vdec_drv_if.h" #include "../aml_vcodec_util.h" #include "../aml_vcodec_dec.h" +#include "../aml_vcodec_drv.h" #include "../aml_vcodec_adapt.h" #include "../vdec_drv_base.h" #include "../aml_vcodec_vfm.h" @@ -112,6 +113,7 @@ struct vdec_hevc_inst { struct aml_vdec_adapt vdec; struct vdec_hevc_vsi *vsi; struct vcodec_vfm_s vfm; + struct aml_dec_params parms; struct completion comp; }; @@ -144,6 +146,54 @@ static void get_dpb_size(struct vdec_hevc_inst *inst, unsigned int *dpb_sz) aml_vcodec_debug(inst, "sz=%d", *dpb_sz); } +static u32 vdec_config_default_parms(u8 *parm) +{ + u8 *pbuf = parm; + + pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;"); + pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:7;"); + pbuf += sprintf(pbuf, "hevc_double_write_mode:16;"); + pbuf += sprintf(pbuf, "hevc_buf_width:4096;"); + pbuf += sprintf(pbuf, "hevc_buf_height:2304;"); + pbuf += sprintf(pbuf, "save_buffer_mode:0;"); + pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_mode:0;"); + pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_endian:0;"); + + return parm - pbuf; +} + +static void vdec_parser_parms(struct vdec_hevc_inst *inst) +{ + struct aml_vcodec_ctx *ctx = inst->ctx; + + if (ctx->config.parm.dec.parms_status & + V4L2_CONFIG_PARM_DECODE_CFGINFO) { + u8 *pbuf = ctx->config.buf; + + pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;"); + pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:%d;", + ctx->config.parm.dec.cfg.ref_buf_margin); + pbuf += sprintf(pbuf, "hevc_double_write_mode:%d;", + ctx->config.parm.dec.cfg.double_write_mode); + pbuf += sprintf(pbuf, "hevc_buf_width:4096;"); + pbuf += sprintf(pbuf, "hevc_buf_height:2304;"); + pbuf += sprintf(pbuf, "save_buffer_mode:0;"); + pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_mode:%d;", + ctx->config.parm.dec.cfg.canvas_mem_mode); + pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_endian:%d;", + ctx->config.parm.dec.cfg.canvas_mem_endian); + ctx->config.length = pbuf - ctx->config.buf; + } else { + ctx->config.parm.dec.cfg.double_write_mode = 16; + ctx->config.parm.dec.cfg.ref_buf_margin = 7; + ctx->config.length = vdec_config_default_parms(ctx->config.buf); + } + + inst->vdec.config = ctx->config; + inst->parms.cfg = ctx->config.parm.dec.cfg; + inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_CFGINFO; +} + static int vdec_hevc_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) { struct vdec_hevc_inst *inst = NULL; @@ -153,12 +203,13 @@ static int vdec_hevc_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) if (!inst) return -ENOMEM; - inst->ctx = ctx; + inst->vdec.video_type = VFORMAT_HEVC; + inst->vdec.dev = ctx->dev->vpu_plat_dev; + inst->vdec.filp = ctx->dev->filp; + inst->vdec.ctx = ctx; + inst->ctx = ctx; - inst->vdec.video_type = VFORMAT_HEVC; - inst->vdec.dev = ctx->dev->vpu_plat_dev; - inst->vdec.filp = ctx->dev->filp; - inst->vdec.ctx = ctx; + vdec_parser_parms(inst); /* set play mode.*/ if (ctx->is_drm_mode) @@ -168,54 +219,53 @@ static int vdec_hevc_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) inst->vdec.port.type = PORT_TYPE_HEVC; /* init vfm */ - inst->vfm.ctx = ctx; - inst->vfm.ada_ctx = &inst->vdec; - vcodec_vfm_init(&inst->vfm); + inst->vfm.ctx = ctx; + inst->vfm.ada_ctx = &inst->vdec; + ret = vcodec_vfm_init(&inst->vfm); + if (ret) { + pr_err("%s, init vfm failed.\n", __func__); + goto err; + } ret = video_decoder_init(&inst->vdec); if (ret) { aml_vcodec_err(inst, "vdec_hevc init err=%d", ret); - goto error_free_inst; + goto err; } /* probe info from the stream */ inst->vsi = kzalloc(sizeof(struct vdec_hevc_vsi), GFP_KERNEL); if (!inst->vsi) { ret = -ENOMEM; - goto error_free_inst; + goto err; } /* alloc the header buffer to be used cache sps or spp etc.*/ inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL); if (!inst->vsi) { ret = -ENOMEM; - goto error_free_vsi; + goto err; } - inst->vsi->pic.visible_width = 1920; - inst->vsi->pic.visible_height = 1080; - inst->vsi->pic.coded_width = 1920; - inst->vsi->pic.coded_height = 1088; - inst->vsi->pic.y_bs_sz = 0; - inst->vsi->pic.y_len_sz = (1920 * 1088); - inst->vsi->pic.c_bs_sz = 0; - inst->vsi->pic.c_len_sz = (1920 * 1088 / 2); - init_completion(&inst->comp); aml_vcodec_debug(inst, "hevc Instance >> %p", inst); - ctx->ada_ctx = &inst->vdec; - *h_vdec = (unsigned long)inst; + ctx->ada_ctx = &inst->vdec; + *h_vdec = (unsigned long)inst; //dump_init(); return 0; - -error_free_vsi: - kfree(inst->vsi); -error_free_inst: - kfree(inst); +err: + if (inst) + vcodec_vfm_release(&inst->vfm); + if (inst && inst->vsi && inst->vsi->header_buf) + kfree(inst->vsi->header_buf); + if (inst && inst->vsi) + kfree(inst->vsi); + if (inst) + kfree(inst); *h_vdec = 0; return ret; @@ -252,17 +302,76 @@ static int refer_buffer_num(struct h265_SPS_t *sps) return used_buf_num; } +static int vdec_get_dw_mode(struct vdec_hevc_inst *inst, int dw_mode) +{ + u32 valid_dw_mode = inst->parms.cfg.double_write_mode; + int w = inst->parms.cfg.init_width; + int h = inst->parms.cfg.init_height; + u32 dw = 0x1; /*1:1*/ + + switch (valid_dw_mode) { + case 0x100: + if (w > 1920 && h > 1088) + dw = 0x4; /*1:2*/ + break; + case 0x200: + if (w > 1920 && h > 1088) + dw = 0x2; /*1:4*/ + break; + case 0x300: + if (w > 1280 && h > 720) + dw = 0x4; /*1:2*/ + break; + default: + dw = valid_dw_mode; + break; + } + + return dw; +} + +static int vdec_pic_scale(struct vdec_hevc_inst *inst, int length, int dw_mode) +{ + int ret = 64; + + switch (vdec_get_dw_mode(inst, dw_mode)) { + case 0x0: /* only afbc, output afbc */ + ret = 64; + break; + case 0x1: /* afbc and (w x h), output YUV420 */ + ret = length; + break; + case 0x2: /* afbc and (w/4 x h/4), output YUV420 */ + case 0x3: /* afbc and (w/4 x h/4), output afbc and YUV420 */ + ret = length >> 2; + break; + case 0x4: /* afbc and (w/2 x h/2), output YUV420 */ + ret = length >> 1; + break; + case 0x10: /* (w x h), output YUV420-8bit)*/ + default: + ret = length; + break; + } + + return ret; +} + static void fill_vdec_params(struct vdec_hevc_inst *inst, struct h265_SPS_t *sps) { struct vdec_pic_info *pic = &inst->vsi->pic; struct vdec_hevc_dec_info *dec = &inst->vsi->dec; struct v4l2_rect *rect = &inst->vsi->crop; + int dw = inst->parms.cfg.double_write_mode; + int margin = inst->parms.cfg.ref_buf_margin; /* fill visible area size that be used for EGL. */ pic->visible_width = sps->width - (sps->output_window.left_offset + sps->output_window.right_offset); pic->visible_height = sps->height - (sps->output_window.top_offset + sps->output_window.bottom_offset); + pic->visible_width = vdec_pic_scale(inst, pic->visible_width, dw); + pic->visible_height = vdec_pic_scale(inst, pic->visible_height, dw); /* calc visible ares. */ rect->left = 0; @@ -271,18 +380,26 @@ static void fill_vdec_params(struct vdec_hevc_inst *inst, struct h265_SPS_t *sps rect->height = pic->visible_height; /* config canvas size that be used for decoder. */ - pic->coded_width = ALIGN(sps->width, 32); - pic->coded_height = ALIGN(sps->height, 32); + pic->coded_width = vdec_pic_scale(inst, ALIGN(sps->width, 32), dw); + pic->coded_height = vdec_pic_scale(inst, ALIGN(sps->height, 32), dw); pic->y_len_sz = pic->coded_width * pic->coded_height; pic->c_len_sz = pic->y_len_sz >> 1; /* calc DPB size */ - dec->dpb_sz = refer_buffer_num(sps); + dec->dpb_sz = refer_buffer_num(sps) + margin; - pr_info("[%d] The stream infos, coded:(%d x %d), visible:(%d x %d), DPB: %d\n", - inst->ctx->id, pic->coded_width, pic->coded_height, - pic->visible_width, pic->visible_height, dec->dpb_sz); + inst->parms.ps.visible_width = pic->visible_width; + inst->parms.ps.visible_height = pic->visible_height; + inst->parms.ps.coded_width = pic->coded_width; + inst->parms.ps.coded_height = pic->coded_height; + inst->parms.ps.dpb_size = dec->dpb_sz; + inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_PSINFO; + + pr_info("[%d] The stream infos, dw: %d, coded:(%d x %d), visible:(%d x %d), DPB: %d, margin: %d\n", + inst->ctx->id, dw, pic->coded_width, pic->coded_height, + pic->visible_width, pic->visible_height, + dec->dpb_sz - margin, margin); } static int stream_parse_by_ucode(struct vdec_hevc_inst *inst, u8 *buf, u32 size) @@ -308,7 +425,7 @@ static int stream_parse(struct vdec_hevc_inst *inst, u8 *buf, u32 size) int ret = 0; struct h265_param_sets *ps = NULL; - ps = kzalloc(sizeof(struct h265_param_sets), GFP_KERNEL); + ps = vzalloc(sizeof(struct h265_param_sets)); if (ps == NULL) return -ENOMEM; @@ -323,7 +440,7 @@ static int stream_parse(struct vdec_hevc_inst *inst, u8 *buf, u32 size) ret = ps->sps_parsed ? 0 : -1; out: - kfree(ps); + vfree(ps); return ret; } @@ -452,19 +569,22 @@ static bool monitor_res_change(struct vdec_hevc_inst *inst, u8 *buf, u32 size) if (type == HEVC_NAL_SPS) { ret = stream_parse(inst, p, len); - if (!ret && (inst->vsi->cur_pic.coded_width != - inst->vsi->pic.coded_width || - inst->vsi->cur_pic.coded_height != - inst->vsi->pic.coded_height)) { - inst->vsi->cur_pic = inst->vsi->pic; - return true; - } + if (ret) + break; } p += j; } p++; } + if (!ret && (inst->vsi->cur_pic.coded_width != + inst->vsi->pic.coded_width || + inst->vsi->cur_pic.coded_height != + inst->vsi->pic.coded_height)) { + inst->vsi->cur_pic = inst->vsi->pic; + return true; + } + return false; } @@ -478,10 +598,12 @@ static int vdec_hevc_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs, u32 size; int ret = -1; - /* bs NULL means flush decoder */ if (bs == NULL) return -1; + if (vdec_input_full(vdec)) + return -EAGAIN; + buf = (u8 *)bs->vaddr; size = bs->size; st = (struct stream_info *)buf; @@ -505,6 +627,23 @@ static int vdec_hevc_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs, return ret; } + static void get_param_config_info(struct vdec_hevc_inst *inst, + struct aml_dec_params *parms) + { + if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_CFGINFO) + parms->cfg = inst->parms.cfg; + if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_PSINFO) + parms->ps = inst->parms.ps; + if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_HDRINFO) + parms->hdr = inst->parms.hdr; + if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_CNTINFO) + parms->cnt = inst->parms.cnt; + + parms->parms_status |= inst->parms.parms_status; + + aml_vcodec_debug(inst, "parms status: %u", parms->parms_status); + } + static int vdec_hevc_get_param(unsigned long h_vdec, enum vdec_get_param_type type, void *out) { @@ -537,6 +676,9 @@ static int vdec_hevc_get_param(unsigned long h_vdec, get_crop_info(inst, out); break; + case GET_PARAM_CONFIG_INFO: + get_param_config_info(inst, out); + break; default: aml_vcodec_err(inst, "invalid get parameter type=%d", type); ret = -EINVAL; @@ -550,16 +692,16 @@ static void set_param_write_sync(struct vdec_hevc_inst *inst) complete(&inst->comp); } -static void set_param_pic_info(struct vdec_hevc_inst *inst, - struct aml_vdec_pic_infos *info) +static void set_param_ps_info(struct vdec_hevc_inst *inst, + struct aml_vdec_ps_infos *ps) { struct vdec_pic_info *pic = &inst->vsi->pic; struct vdec_hevc_dec_info *dec = &inst->vsi->dec; struct v4l2_rect *rect = &inst->vsi->crop; /* fill visible area size that be used for EGL. */ - pic->visible_width = info->visible_width; - pic->visible_height = info->visible_height; + pic->visible_width = ps->visible_width; + pic->visible_height = ps->visible_height; /* calc visible ares. */ rect->left = 0; @@ -568,12 +710,16 @@ static void set_param_pic_info(struct vdec_hevc_inst *inst, rect->height = pic->visible_height; /* config canvas size that be used for decoder. */ - pic->coded_width = ALIGN(info->coded_width, 64); - pic->coded_height = ALIGN(info->coded_height, 64); + pic->coded_width = ALIGN(ps->coded_width, 64); + pic->coded_height = ALIGN(ps->coded_height, 64); pic->y_len_sz = pic->coded_width * pic->coded_height; pic->c_len_sz = pic->y_len_sz >> 1; - dec->dpb_sz = info->dpb_size; + dec->dpb_sz = ps->dpb_size; + + inst->parms.ps = *ps; + inst->parms.parms_status |= + V4L2_CONFIG_PARM_DECODE_PSINFO; /*wake up*/ complete(&inst->comp); @@ -584,6 +730,26 @@ static void set_param_pic_info(struct vdec_hevc_inst *inst, dec->dpb_sz); } +static void set_param_hdr_info(struct vdec_hevc_inst *inst, + struct aml_vdec_hdr_infos *hdr) +{ + if (!(inst->parms.parms_status & + V4L2_CONFIG_PARM_DECODE_HDRINFO)) { + inst->parms.hdr = *hdr; + inst->parms.parms_status |= + V4L2_CONFIG_PARM_DECODE_HDRINFO; + aml_vdec_dispatch_event(inst->ctx, + V4L2_EVENT_SRC_CH_HDRINFO); + pr_info("H265 set HDR infos\n"); + } +} + +static void set_param_post_event(struct vdec_hevc_inst *inst, u32 *event) +{ + aml_vdec_dispatch_event(inst->ctx, *event); + pr_info("H265 post event: %d\n", *event); +} + static int vdec_hevc_set_param(unsigned long h_vdec, enum vdec_set_param_type type, void *in) { @@ -600,10 +766,17 @@ static int vdec_hevc_set_param(unsigned long h_vdec, set_param_write_sync(inst); break; - case SET_PARAM_PIC_INFO: - set_param_pic_info(inst, in); + case SET_PARAM_PS_INFO: + set_param_ps_info(inst, in); break; + case SET_PARAM_HDR_INFO: + set_param_hdr_info(inst, in); + break; + + case SET_PARAM_POST_EVENT: + set_param_post_event(inst, in); + break; default: aml_vcodec_err(inst, "invalid set parameter type=%d", type); ret = -EINVAL; diff --git a/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c b/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c index 8bc5faa..0db4eca 100644 --- a/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c +++ b/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c @@ -151,12 +151,12 @@ static int vdec_mjpeg_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) if (!inst) return -ENOMEM; - inst->ctx = ctx; - - inst->vdec.video_type = VFORMAT_MJPEG; - inst->vdec.dev = ctx->dev->vpu_plat_dev; - inst->vdec.filp = ctx->dev->filp; - inst->vdec.ctx = ctx; + inst->vdec.video_type = VFORMAT_MJPEG; + inst->vdec.dev = ctx->dev->vpu_plat_dev; + inst->vdec.filp = ctx->dev->filp; + inst->vdec.config = ctx->config; + inst->vdec.ctx = ctx; + inst->ctx = ctx; /* set play mode.*/ if (ctx->is_drm_mode) @@ -194,15 +194,15 @@ static int vdec_mjpeg_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) inst->vsi->pic.visible_height = 1080; inst->vsi->pic.coded_width = 1920; inst->vsi->pic.coded_height = 1088; - inst->vsi->pic.y_bs_sz = 0; - inst->vsi->pic.y_len_sz = (1920 * 1088); - inst->vsi->pic.c_bs_sz = 0; - inst->vsi->pic.c_len_sz = (1920 * 1088 / 2); + inst->vsi->pic.y_bs_sz = 0; + inst->vsi->pic.y_len_sz = (1920 * 1088); + inst->vsi->pic.c_bs_sz = 0; + inst->vsi->pic.c_len_sz = (1920 * 1088 / 2); aml_vcodec_debug(inst, "mjpeg Instance >> %p", inst); - ctx->ada_ctx = &inst->vdec; - *h_vdec = (unsigned long)inst; + ctx->ada_ctx = &inst->vdec; + *h_vdec = (unsigned long)inst; //dump_init(); @@ -451,8 +451,8 @@ static int vdec_mjpeg_get_param(unsigned long h_vdec, return ret; } -static void set_param_pic_info(struct vdec_mjpeg_inst *inst, - struct aml_vdec_pic_infos *info) +static void set_param_ps_info(struct vdec_mjpeg_inst *inst, + struct aml_vdec_ps_infos *ps) { pr_info("---%s, %d\n", __func__, __LINE__); } @@ -469,8 +469,8 @@ static int vdec_mjpeg_set_param(unsigned long h_vdec, } switch (type) { - case SET_PARAM_PIC_INFO: - set_param_pic_info(inst, in); + case SET_PARAM_PS_INFO: + set_param_ps_info(inst, in); break; default: diff --git a/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c b/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c index cdde95b..5d5ca07 100644 --- a/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c +++ b/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c @@ -151,12 +151,12 @@ static int vdec_mpeg12_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) if (!inst) return -ENOMEM; - inst->ctx = ctx; - - inst->vdec.video_type = VFORMAT_MPEG12; - inst->vdec.dev = ctx->dev->vpu_plat_dev; - inst->vdec.filp = ctx->dev->filp; - inst->vdec.ctx = ctx; + inst->vdec.video_type = VFORMAT_MPEG12; + inst->vdec.dev = ctx->dev->vpu_plat_dev; + inst->vdec.filp = ctx->dev->filp; + inst->vdec.config = ctx->config; + inst->vdec.ctx = ctx; + inst->ctx = ctx; /* set play mode.*/ if (ctx->is_drm_mode) @@ -166,8 +166,8 @@ static int vdec_mpeg12_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) inst->vdec.port.type = PORT_TYPE_VIDEO; /* init vfm */ - inst->vfm.ctx = ctx; - inst->vfm.ada_ctx = &inst->vdec; + inst->vfm.ctx = ctx; + inst->vfm.ada_ctx = &inst->vdec; vcodec_vfm_init(&inst->vfm); ret = video_decoder_init(&inst->vdec); @@ -194,15 +194,15 @@ static int vdec_mpeg12_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) inst->vsi->pic.visible_height = 1080; inst->vsi->pic.coded_width = 1920; inst->vsi->pic.coded_height = 1088; - inst->vsi->pic.y_bs_sz = 0; - inst->vsi->pic.y_len_sz = (1920 * 1088); - inst->vsi->pic.c_bs_sz = 0; - inst->vsi->pic.c_len_sz = (1920 * 1088 / 2); + inst->vsi->pic.y_bs_sz = 0; + inst->vsi->pic.y_len_sz = (1920 * 1088); + inst->vsi->pic.c_bs_sz = 0; + inst->vsi->pic.c_len_sz = (1920 * 1088 / 2); aml_vcodec_debug(inst, "mpeg12 Instance >> %p", inst); - ctx->ada_ctx = &inst->vdec; - *h_vdec = (unsigned long)inst; + ctx->ada_ctx = &inst->vdec; + *h_vdec = (unsigned long)inst; //dump_init(); @@ -443,8 +443,8 @@ static int vdec_mpeg12_get_param(unsigned long h_vdec, return ret; } -static void set_param_pic_info(struct vdec_mpeg12_inst *inst, - struct aml_vdec_pic_infos *info) +static void set_param_ps_info(struct vdec_mpeg12_inst *inst, + struct aml_vdec_ps_infos *ps) { pr_info("---%s, %d\n", __func__, __LINE__); } @@ -461,8 +461,8 @@ static int vdec_mpeg12_set_param(unsigned long h_vdec, } switch (type) { - case SET_PARAM_PIC_INFO: - set_param_pic_info(inst, in); + case SET_PARAM_PS_INFO: + set_param_ps_info(inst, in); break; default: diff --git a/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c b/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c index 7a40a4a..ab428af 100644 --- a/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c +++ b/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c @@ -151,24 +151,24 @@ static int vdec_mpeg4_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) if (!inst) return -ENOMEM; - inst->ctx = ctx; - - inst->vdec.video_type = VFORMAT_MPEG4; - inst->vdec.format = VIDEO_DEC_FORMAT_MPEG4_5; - inst->vdec.dev = ctx->dev->vpu_plat_dev; - inst->vdec.filp = ctx->dev->filp; - inst->vdec.ctx = ctx; + inst->vdec.video_type = VFORMAT_MPEG4; + inst->vdec.format = VIDEO_DEC_FORMAT_MPEG4_5; + inst->vdec.dev = ctx->dev->vpu_plat_dev; + inst->vdec.filp = ctx->dev->filp; + inst->vdec.config = ctx->config; + inst->vdec.ctx = ctx; + inst->ctx = ctx; /* set play mode.*/ if (ctx->is_drm_mode) inst->vdec.port.flag |= PORT_FLAG_DRM; /* to eable mpeg4 hw.*/ - inst->vdec.port.type = PORT_TYPE_VIDEO; + inst->vdec.port.type = PORT_TYPE_VIDEO; /* init vfm */ - inst->vfm.ctx = ctx; - inst->vfm.ada_ctx = &inst->vdec; + inst->vfm.ctx = ctx; + inst->vfm.ada_ctx = &inst->vdec; vcodec_vfm_init(&inst->vfm); ret = video_decoder_init(&inst->vdec); @@ -195,15 +195,15 @@ static int vdec_mpeg4_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) inst->vsi->pic.visible_height = 1080; inst->vsi->pic.coded_width = 1920; inst->vsi->pic.coded_height = 1088; - inst->vsi->pic.y_bs_sz = 0; - inst->vsi->pic.y_len_sz = (1920 * 1088); - inst->vsi->pic.c_bs_sz = 0; - inst->vsi->pic.c_len_sz = (1920 * 1088 / 2); + inst->vsi->pic.y_bs_sz = 0; + inst->vsi->pic.y_len_sz = (1920 * 1088); + inst->vsi->pic.c_bs_sz = 0; + inst->vsi->pic.c_len_sz = (1920 * 1088 / 2); aml_vcodec_debug(inst, "mpeg4 Instance >> %p", inst); - ctx->ada_ctx = &inst->vdec; - *h_vdec = (unsigned long)inst; + ctx->ada_ctx = &inst->vdec; + *h_vdec = (unsigned long)inst; //dump_init(); @@ -452,8 +452,8 @@ static int vdec_mpeg4_get_param(unsigned long h_vdec, return ret; } -static void set_param_pic_info(struct vdec_mpeg4_inst *inst, - struct aml_vdec_pic_infos *info) +static void set_param_ps_info(struct vdec_mpeg4_inst *inst, + struct aml_vdec_ps_infos *ps) { pr_info("---%s, %d\n", __func__, __LINE__); } @@ -470,8 +470,8 @@ static int vdec_mpeg4_set_param(unsigned long h_vdec, } switch (type) { - case SET_PARAM_PIC_INFO: - set_param_pic_info(inst, in); + case SET_PARAM_PS_INFO: + set_param_ps_info(inst, in); break; default: diff --git a/drivers/amvdec_ports/decoder/vdec_vp9_if.c b/drivers/amvdec_ports/decoder/vdec_vp9_if.c index 5b3bbab..7d395ba 100644 --- a/drivers/amvdec_ports/decoder/vdec_vp9_if.c +++ b/drivers/amvdec_ports/decoder/vdec_vp9_if.c @@ -26,12 +26,16 @@ #include "../vdec_drv_if.h" #include "../aml_vcodec_util.h" #include "../aml_vcodec_dec.h" +#include "../aml_vcodec_drv.h" #include "../aml_vcodec_adapt.h" #include "../vdec_drv_base.h" #include "../aml_vcodec_vfm.h" #include "aml_vp9_parser.h" #include "vdec_vp9_trigger.h" +#define KERNEL_ATRACE_TAG KERNEL_ATRACE_TAG_V4L2 +#include <trace/events/meson_atrace.h> + #define PREFIX_SIZE (16) #define NAL_TYPE(value) ((value) & 0x1F) @@ -120,6 +124,7 @@ struct vdec_vp9_inst { struct aml_vdec_adapt vdec; struct vdec_vp9_vsi *vsi; struct vcodec_vfm_s vfm; + struct aml_dec_params parms; struct completion comp; }; @@ -155,6 +160,94 @@ static void get_dpb_size(struct vdec_vp9_inst *inst, unsigned int *dpb_sz) aml_vcodec_debug(inst, "sz=%d", *dpb_sz); } +static u32 vdec_config_default_parms(u8 *parm) +{ + u8 *pbuf = parm; + + pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;"); + pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:7;"); + pbuf += sprintf(pbuf, "vp9_double_write_mode:16;"); + pbuf += sprintf(pbuf, "vp9_buf_width:1920;"); + pbuf += sprintf(pbuf, "vp9_buf_height:1088;"); + pbuf += sprintf(pbuf, "vp9_max_pic_w:4096;"); + pbuf += sprintf(pbuf, "vp9_max_pic_h:2304;"); + pbuf += sprintf(pbuf, "save_buffer_mode:0;"); + pbuf += sprintf(pbuf, "no_head:0;"); + pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_mode:0;"); + pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_endian:0;"); + + return parm - pbuf; +} + +static void vdec_parser_parms(struct vdec_vp9_inst *inst) +{ + struct aml_vcodec_ctx *ctx = inst->ctx; + + if (ctx->config.parm.dec.parms_status & + V4L2_CONFIG_PARM_DECODE_CFGINFO) { + u8 *pbuf = ctx->config.buf; + + pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;"); + pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:%d;", + ctx->config.parm.dec.cfg.ref_buf_margin); + pbuf += sprintf(pbuf, "vp9_double_write_mode:%d;", + ctx->config.parm.dec.cfg.double_write_mode); + pbuf += sprintf(pbuf, "vp9_buf_width:%d;", + ctx->config.parm.dec.cfg.init_width); + pbuf += sprintf(pbuf, "vp9_buf_height:%d;", + ctx->config.parm.dec.cfg.init_height); + pbuf += sprintf(pbuf, "save_buffer_mode:0;"); + pbuf += sprintf(pbuf, "no_head:0;"); + pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_mode:%d;", + ctx->config.parm.dec.cfg.canvas_mem_mode); + pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_endian:%d;", + ctx->config.parm.dec.cfg.canvas_mem_endian); + ctx->config.length = pbuf - ctx->config.buf; + } else { + ctx->config.parm.dec.cfg.double_write_mode = 16; + ctx->config.parm.dec.cfg.ref_buf_margin = 7; + ctx->config.length = vdec_config_default_parms(ctx->config.buf); + } + + if ((ctx->config.parm.dec.parms_status & + V4L2_CONFIG_PARM_DECODE_HDRINFO) && + inst->parms.hdr.color_parms.present_flag) { + u8 *pbuf = ctx->config.buf + ctx->config.length; + + pbuf += sprintf(pbuf, "mG.x:%d;", + ctx->config.parm.dec.hdr.color_parms.primaries[0][0]); + pbuf += sprintf(pbuf, "mG.y:%d;", + ctx->config.parm.dec.hdr.color_parms.primaries[0][1]); + pbuf += sprintf(pbuf, "mB.x:%d;", + ctx->config.parm.dec.hdr.color_parms.primaries[1][0]); + pbuf += sprintf(pbuf, "mB.y:%d;", + ctx->config.parm.dec.hdr.color_parms.primaries[1][1]); + pbuf += sprintf(pbuf, "mR.x:%d;", + ctx->config.parm.dec.hdr.color_parms.primaries[2][0]); + pbuf += sprintf(pbuf, "mR.y:%d;", + ctx->config.parm.dec.hdr.color_parms.primaries[2][1]); + pbuf += sprintf(pbuf, "mW.x:%d;", + ctx->config.parm.dec.hdr.color_parms.white_point[0]); + pbuf += sprintf(pbuf, "mW.y:%d;", + ctx->config.parm.dec.hdr.color_parms.white_point[1]); + pbuf += sprintf(pbuf, "mMaxDL:%d;", + ctx->config.parm.dec.hdr.color_parms.luminance[0] / 1000); + pbuf += sprintf(pbuf, "mMinDL:%d;", + ctx->config.parm.dec.hdr.color_parms.luminance[1]); + pbuf += sprintf(pbuf, "mMaxCLL:%d;", + ctx->config.parm.dec.hdr.color_parms.content_light_level.max_content); + pbuf += sprintf(pbuf, "mMaxFALL:%d;", + ctx->config.parm.dec.hdr.color_parms.content_light_level.max_pic_average); + ctx->config.length = pbuf - ctx->config.buf; + inst->parms.hdr = ctx->config.parm.dec.hdr; + inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_HDRINFO; + } + + inst->vdec.config = ctx->config; + inst->parms.cfg = ctx->config.parm.dec.cfg; + inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_CFGINFO; +} + static int vdec_vp9_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) { struct vdec_vp9_inst *inst = NULL; @@ -164,70 +257,70 @@ static int vdec_vp9_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) if (!inst) return -ENOMEM; - inst->ctx = ctx; + inst->vdec.video_type = VFORMAT_VP9; + inst->vdec.dev = ctx->dev->vpu_plat_dev; + inst->vdec.filp = ctx->dev->filp; + inst->vdec.ctx = ctx; + inst->ctx = ctx; - inst->vdec.video_type = VFORMAT_VP9; - inst->vdec.dev = ctx->dev->vpu_plat_dev; - inst->vdec.filp = ctx->dev->filp; - inst->vdec.ctx = ctx; + vdec_parser_parms(inst); /* set play mode.*/ if (ctx->is_drm_mode) inst->vdec.port.flag |= PORT_FLAG_DRM; /* to eable vp9 hw.*/ - inst->vdec.port.type = PORT_TYPE_HEVC; + inst->vdec.port.type = PORT_TYPE_HEVC; /* init vfm */ - inst->vfm.ctx = ctx; - inst->vfm.ada_ctx = &inst->vdec; - vcodec_vfm_init(&inst->vfm); + inst->vfm.ctx = ctx; + inst->vfm.ada_ctx = &inst->vdec; + ret = vcodec_vfm_init(&inst->vfm); + if (ret) { + pr_err("%s, init vfm failed.\n", __func__); + goto err; + } /* probe info from the stream */ inst->vsi = kzalloc(sizeof(struct vdec_vp9_vsi), GFP_KERNEL); if (!inst->vsi) { ret = -ENOMEM; - goto error_free_inst; + goto err; } /* alloc the header buffer to be used cache sps or spp etc.*/ inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL); if (!inst->vsi) { ret = -ENOMEM; - goto error_free_vsi; + goto err; } - inst->vsi->pic.visible_width = 1920; - inst->vsi->pic.visible_height = 1080; - inst->vsi->pic.coded_width = 1920; - inst->vsi->pic.coded_height = 1088; - inst->vsi->pic.y_bs_sz = 0; - inst->vsi->pic.y_len_sz = (1920 * 1088); - inst->vsi->pic.c_bs_sz = 0; - inst->vsi->pic.c_len_sz = (1920 * 1088 / 2); - init_completion(&inst->comp); aml_vcodec_debug(inst, "vp9 Instance >> %p", inst); - ctx->ada_ctx = &inst->vdec; - *h_vdec = (unsigned long)inst; + ctx->ada_ctx = &inst->vdec; + *h_vdec = (unsigned long)inst; /* init decoder. */ ret = video_decoder_init(&inst->vdec); if (ret) { aml_vcodec_err(inst, "vdec_vp9 init err=%d", ret); - goto error_free_inst; + goto err; } //dump_init(); return 0; - -error_free_vsi: - kfree(inst->vsi); -error_free_inst: - kfree(inst); +err: + if (inst) + vcodec_vfm_release(&inst->vfm); + if (inst && inst->vsi && inst->vsi->header_buf) + kfree(inst->vsi->header_buf); + if (inst && inst->vsi) + kfree(inst->vsi); + if (inst) + kfree(inst); *h_vdec = 0; return ret; @@ -241,16 +334,73 @@ static int refer_buffer_num(int level_idc, int poc_cnt, } #endif +static int vdec_get_dw_mode(struct vdec_vp9_inst *inst, int dw_mode) +{ + u32 valid_dw_mode = inst->parms.cfg.double_write_mode; + int w = inst->parms.cfg.init_width; + int h = inst->parms.cfg.init_height; + u32 dw = 0x1; /*1:1*/ + + switch (valid_dw_mode) { + case 0x100: + if (w > 1920 && h > 1088) + dw = 0x4; /*1:2*/ + break; + case 0x200: + if (w > 1920 && h > 1088) + dw = 0x2; /*1:4*/ + break; + case 0x300: + if (w > 1280 && h > 720) + dw = 0x4; /*1:2*/ + break; + default: + dw = valid_dw_mode; + break; + } + + return dw; +} + +static int vdec_pic_scale(struct vdec_vp9_inst *inst, int length, int dw_mode) +{ + int ret = 64; + + switch (vdec_get_dw_mode(inst, dw_mode)) { + case 0x0: /* only afbc, output afbc */ + ret = 64; + break; + case 0x1: /* afbc and (w x h), output YUV420 */ + ret = length; + break; + case 0x2: /* afbc and (w/4 x h/4), output YUV420 */ + case 0x3: /* afbc and (w/4 x h/4), output afbc and YUV420 */ + ret = length >> 2; + break; + case 0x4: /* afbc and (w/2 x h/2), output YUV420 */ + ret = length >> 1; + break; + case 0x10: /* (w x h), output YUV420-8bit) */ + default: + ret = length; + break; + } + + return ret; +} + static void fill_vdec_params(struct vdec_vp9_inst *inst, struct VP9Context *vp9_ctx) { struct vdec_pic_info *pic = &inst->vsi->pic; struct vdec_vp9_dec_info *dec = &inst->vsi->dec; struct v4l2_rect *rect = &inst->vsi->crop; + int dw = inst->parms.cfg.double_write_mode; + int margin = inst->parms.cfg.ref_buf_margin; /* fill visible area size that be used for EGL. */ - pic->visible_width = vp9_ctx->render_width; - pic->visible_height = vp9_ctx->render_height; + pic->visible_width = vdec_pic_scale(inst, vp9_ctx->render_width, dw); + pic->visible_height = vdec_pic_scale(inst, vp9_ctx->render_height, dw); /* calc visible ares. */ rect->left = 0; @@ -259,18 +409,26 @@ static void fill_vdec_params(struct vdec_vp9_inst *inst, rect->height = pic->visible_height; /* config canvas size that be used for decoder. */ - pic->coded_width = ALIGN(vp9_ctx->width, 32); - pic->coded_height = ALIGN(vp9_ctx->height, 32); + pic->coded_width = vdec_pic_scale(inst, ALIGN(vp9_ctx->width, 32), dw); + pic->coded_height = vdec_pic_scale(inst, ALIGN(vp9_ctx->height, 32), dw); pic->y_len_sz = pic->coded_width * pic->coded_height; pic->c_len_sz = pic->y_len_sz >> 1; /* calc DPB size */ - dec->dpb_sz = 5;//refer_buffer_num(sps->level_idc, poc_cnt, mb_w, mb_h); - - aml_vcodec_debug(inst, "[%d] The stream infos, coded:(%d x %d), visible:(%d x %d), DPB: %d\n", - inst->ctx->id, pic->coded_width, pic->coded_height, - pic->visible_width, pic->visible_height, dec->dpb_sz); + dec->dpb_sz = 5 + margin;//refer_buffer_num(sps->level_idc, poc_cnt, mb_w, mb_h); + + inst->parms.ps.visible_width = pic->visible_width; + inst->parms.ps.visible_height = pic->visible_height; + inst->parms.ps.coded_width = pic->coded_width; + inst->parms.ps.coded_height = pic->coded_height; + inst->parms.ps.dpb_size = dec->dpb_sz; + inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_PSINFO; + + aml_vcodec_debug(inst, "[%d] The stream infos, dw: %d, coded:(%d x %d), visible:(%d x %d), DPB: %d, margin: %d\n", + inst->ctx->id, dw, pic->coded_width, pic->coded_height, + pic->visible_width, pic->visible_height, + dec->dpb_sz - margin, margin); } static int stream_parse_by_ucode(struct vdec_vp9_inst *inst, u8 *buf, u32 size) @@ -295,7 +453,7 @@ static int stream_parse(struct vdec_vp9_inst *inst, u8 *buf, u32 size) int ret = 0; struct vp9_param_sets *ps = NULL; - ps = kzalloc(sizeof(struct vp9_param_sets), GFP_KERNEL); + ps = vzalloc(sizeof(struct vp9_param_sets)); if (ps == NULL) return -ENOMEM; @@ -310,7 +468,7 @@ static int stream_parse(struct vdec_vp9_inst *inst, u8 *buf, u32 size) ret = ps->head_parsed ? 0 : -1; out: - kfree(ps); + vfree(ps); return ret; } @@ -550,10 +708,14 @@ static int vdec_vp9_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs, u32 size; int ret = -1; - /* bs NULL means flush decoder */ if (bs == NULL) return -1; + if (vdec_input_full(vdec)) { + ATRACE_COUNTER("vdec_input_full", 0); + return -EAGAIN; + } + buf = (u8 *)bs->vaddr; size = bs->size; st = (struct stream_info *)buf; @@ -573,10 +735,28 @@ static int vdec_vp9_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs, ret = vdec_write_nalu(inst, buf, size, timestamp); } + ATRACE_COUNTER("v4l2_decode_write", ret); return ret; } + static void get_param_config_info(struct vdec_vp9_inst *inst, + struct aml_dec_params *parms) + { + if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_CFGINFO) + parms->cfg = inst->parms.cfg; + if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_PSINFO) + parms->ps = inst->parms.ps; + if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_HDRINFO) + parms->hdr = inst->parms.hdr; + if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_CNTINFO) + parms->cnt = inst->parms.cnt; + + parms->parms_status |= inst->parms.parms_status; + + aml_vcodec_debug(inst, "parms status: %u", parms->parms_status); + } + static int vdec_vp9_get_param(unsigned long h_vdec, enum vdec_get_param_type type, void *out) { @@ -609,6 +789,9 @@ static int vdec_vp9_get_param(unsigned long h_vdec, get_crop_info(inst, out); break; + case GET_PARAM_CONFIG_INFO: + get_param_config_info(inst, out); + break; default: aml_vcodec_err(inst, "invalid get parameter type=%d", type); ret = -EINVAL; @@ -622,16 +805,16 @@ static void set_param_write_sync(struct vdec_vp9_inst *inst) complete(&inst->comp); } -static void set_param_pic_info(struct vdec_vp9_inst *inst, - struct aml_vdec_pic_infos *info) +static void set_param_ps_info(struct vdec_vp9_inst *inst, + struct aml_vdec_ps_infos *ps) { struct vdec_pic_info *pic = &inst->vsi->pic; struct vdec_vp9_dec_info *dec = &inst->vsi->dec; struct v4l2_rect *rect = &inst->vsi->crop; /* fill visible area size that be used for EGL. */ - pic->visible_width = info->visible_width; - pic->visible_height = info->visible_height; + pic->visible_width = ps->visible_width; + pic->visible_height = ps->visible_height; /* calc visible ares. */ rect->left = 0; @@ -640,22 +823,46 @@ static void set_param_pic_info(struct vdec_vp9_inst *inst, rect->height = pic->visible_height; /* config canvas size that be used for decoder. */ - pic->coded_width = info->coded_width; - pic->coded_height = info->coded_height; + pic->coded_width = ps->coded_width; + pic->coded_height = ps->coded_height; pic->y_len_sz = pic->coded_width * pic->coded_height; pic->c_len_sz = pic->y_len_sz >> 1; /* calc DPB size */ - dec->dpb_sz = 5; + dec->dpb_sz = 5; + + inst->parms.ps = *ps; + inst->parms.parms_status |= + V4L2_CONFIG_PARM_DECODE_PSINFO; /*wake up*/ complete(&inst->comp); pr_info("Parse from ucode, crop(%d x %d), coded(%d x %d) dpb: %d\n", - info->visible_width, info->visible_height, - info->coded_width, info->coded_height, - info->dpb_size); + ps->visible_width, ps->visible_height, + ps->coded_width, ps->coded_height, + ps->dpb_size); +} + +static void set_param_hdr_info(struct vdec_vp9_inst *inst, + struct aml_vdec_hdr_infos *hdr) +{ + if ((inst->parms.parms_status & + V4L2_CONFIG_PARM_DECODE_HDRINFO)) { + inst->parms.hdr = *hdr; + inst->parms.parms_status |= + V4L2_CONFIG_PARM_DECODE_HDRINFO; + aml_vdec_dispatch_event(inst->ctx, + V4L2_EVENT_SRC_CH_HDRINFO); + pr_info("VP9 set HDR infos\n"); + } +} + +static void set_param_post_event(struct vdec_vp9_inst *inst, u32 *event) +{ + aml_vdec_dispatch_event(inst->ctx, *event); + pr_info("VP9 post event: %d\n", *event); } static int vdec_vp9_set_param(unsigned long h_vdec, @@ -674,10 +881,17 @@ static int vdec_vp9_set_param(unsigned long h_vdec, set_param_write_sync(inst); break; - case SET_PARAM_PIC_INFO: - set_param_pic_info(inst, in); + case SET_PARAM_PS_INFO: + set_param_ps_info(inst, in); break; + case SET_PARAM_HDR_INFO: + set_param_hdr_info(inst, in); + break; + + case SET_PARAM_POST_EVENT: + set_param_post_event(inst, in); + break; default: aml_vcodec_err(inst, "invalid set parameter type=%d", type); ret = -EINVAL; diff --git a/drivers/amvdec_ports/vdec_drv_if.h b/drivers/amvdec_ports/vdec_drv_if.h index 29e48d3..d3ccef2 100644 --- a/drivers/amvdec_ports/vdec_drv_if.h +++ b/drivers/amvdec_ports/vdec_drv_if.h @@ -68,15 +68,18 @@ enum vdec_get_param_type { GET_PARAM_FREE_FRAME_BUFFER, GET_PARAM_PIC_INFO, GET_PARAM_CROP_INFO, - GET_PARAM_DPB_SIZE + GET_PARAM_DPB_SIZE, + GET_PARAM_CONFIG_INFO }; /* - * SET_PARAM_PIC_INFO : set picture info, data parsed from ucode. + * SET_PARAM_PS_INFO : set picture parms, data parsed from ucode. */ enum vdec_set_param_type { SET_PARAM_WRITE_FRAME_SYNC, - SET_PARAM_PIC_INFO, + SET_PARAM_PS_INFO, + SET_PARAM_HDR_INFO, + SET_PARAM_POST_EVENT }; /** diff --git a/drivers/frame_provider/decoder/avs2/vavs2.c b/drivers/frame_provider/decoder/avs2/vavs2.c index 6258a75..f90fee6 100644 --- a/drivers/frame_provider/decoder/avs2/vavs2.c +++ b/drivers/frame_provider/decoder/avs2/vavs2.c @@ -761,6 +761,7 @@ struct AVS2Decoder_s { #endif int frameinfo_enable; struct vframe_qos_s vframe_qos; + u32 dynamic_buf_margin; }; static int compute_losless_comp_body_size( @@ -3885,7 +3886,7 @@ static int avs2_local_init(struct AVS2Decoder_s *dec) #ifndef AVS2_10B_MMU init_buf_list(dec); #else - dec->used_buf_num = max_buf_num; + dec->used_buf_num = max_buf_num + dec->dynamic_buf_margin; if (dec->used_buf_num > MAX_BUF_NUM) dec->used_buf_num = MAX_BUF_NUM; if (dec->used_buf_num > FRAME_BUFFERS) @@ -7318,6 +7319,13 @@ static int ammvdec_avs2_probe(struct platform_device *pdev) dec->double_write_mode = config_val; else dec->double_write_mode = double_write_mode; + + if (get_config_int(pdata->config, "parm_v4l_buffer_margin", + &config_val) == 0) + dec->dynamic_buf_margin = config_val; + else + dec->dynamic_buf_margin = 0; + if (get_config_int(pdata->config, "HDRStaticInfo", &vf_dp.present_flag) == 0 && vf_dp.present_flag == 1) { @@ -7363,6 +7371,7 @@ static int ammvdec_avs2_probe(struct platform_device *pdev) dec->vavs2_amstream_dec_info.height = 0; dec->vavs2_amstream_dec_info.rate = 30;*/ dec->double_write_mode = double_write_mode; + dec->dynamic_buf_margin = dynamic_buf_num_margin; } video_signal_type = dec->video_signal_type; diff --git a/drivers/frame_provider/decoder/h264/vh264_mvc.c b/drivers/frame_provider/decoder/h264/vh264_mvc.c index fdb0535..821b3c1 100644 --- a/drivers/frame_provider/decoder/h264/vh264_mvc.c +++ b/drivers/frame_provider/decoder/h264/vh264_mvc.c @@ -46,6 +46,7 @@ #include <linux/amlogic/media/codec_mm/configs.h> #include "../utils/firmware.h" #include <linux/amlogic/tee.h> +#include "../utils/config_parser.h" #define TIME_TASK_PRINT_ENABLE 0x100 #define PUT_PRINT_ENABLE 0x200 @@ -185,9 +186,11 @@ static s32 vh264mvc_init(void); unsigned int DECODE_BUFFER_START = 0x00200000; unsigned int DECODE_BUFFER_END = 0x05000000; +/* #define DISPLAY_BUFFER_NUM 4 */ +static unsigned int dynamic_buf_num_margin = 8; + #define DECODE_BUFFER_NUM_MAX 16 -#define DISPLAY_BUFFER_NUM 4 -#define MAX_BMMU_BUFFER_NUM (DECODE_BUFFER_NUM_MAX + DISPLAY_BUFFER_NUM) +#define MAX_BMMU_BUFFER_NUM (DECODE_BUFFER_NUM_MAX + dynamic_buf_num_margin) #define TOTAL_BMMU_BUFF_NUM (MAX_BMMU_BUFFER_NUM * 2 + 3) #define VF_BUFFER_IDX(n) (2 + n) @@ -223,8 +226,12 @@ struct buffer_spec_s { unsigned long phy_addr; int alloc_count; }; +/* static struct buffer_spec_s buffer_spec0[MAX_BMMU_BUFFER_NUM]; static struct buffer_spec_s buffer_spec1[MAX_BMMU_BUFFER_NUM]; +*/ +static struct buffer_spec_s *buffer_spec0; +static struct buffer_spec_s *buffer_spec1; static void *mm_blk_handle; /* @@ -741,7 +748,7 @@ static void do_alloc_work(struct work_struct *work) mb_width, mb_height); total_dec_frame_buffering[0] = - max_dec_frame_buffering[0] + DISPLAY_BUFFER_NUM; + max_dec_frame_buffering[0] + dynamic_buf_num_margin; mb_width = (mb_width + 3) & 0xfffffffc; mb_height = (mb_height + 3) & 0xfffffffc; @@ -822,7 +829,7 @@ static void do_alloc_work(struct work_struct *work) } total_dec_frame_buffering[1] = - max_dec_frame_buffering[1] + DISPLAY_BUFFER_NUM; + max_dec_frame_buffering[1] + dynamic_buf_num_margin; mb_width = (mb_width + 3) & 0xfffffffc; mb_height = (mb_height + 3) & 0xfffffffc; @@ -1369,6 +1376,7 @@ static int vh264mvc_local_init(void) max_dec_frame_buffering[1] = -1; fill_ptr = get_ptr = put_ptr = putting_ptr = 0; dirty_frame_num = 0; + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { view0_vfbuf_use[i] = 0; view1_vfbuf_use[i] = 0; @@ -1412,7 +1420,6 @@ static s32 vh264mvc_init(void) { int ret = -1; char *buf = vmalloc(0x1000 * 16); - if (buf == NULL) return -ENOMEM; @@ -1582,6 +1589,7 @@ static void error_do_work(struct work_struct *work) static int amvdec_h264mvc_probe(struct platform_device *pdev) { struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; + int config_val = 0; pr_info("amvdec_h264mvc probe start.\n"); mutex_lock(&vh264_mvc_mutex); @@ -1603,13 +1611,28 @@ static int amvdec_h264mvc_probe(struct platform_device *pdev) if (pdata->sys_info) vh264mvc_amstream_dec_info = *pdata->sys_info; + if (pdata->config_len) { + pr_info("pdata->config: %s\n", pdata->config); + if (get_config_int(pdata->config, "parm_v4l_buffer_margin", + &config_val) == 0) + dynamic_buf_num_margin = config_val; + } + pdata->dec_status = vh264mvc_dec_status; /* pdata->set_trickmode = vh264mvc_set_trickmode; */ + buffer_spec0 = (struct buffer_spec_s *)vzalloc( + sizeof(struct buffer_spec_s) * MAX_BMMU_BUFFER_NUM * 2); + if (NULL == buffer_spec0) + return -ENOMEM; + buffer_spec1 = &buffer_spec0[MAX_BMMU_BUFFER_NUM]; + if (vh264mvc_init() < 0) { pr_info("\namvdec_h264mvc init failed.\n"); kfree(gvs); gvs = NULL; + vfree(buffer_spec0); + buffer_spec0 = NULL; mutex_unlock(&vh264_mvc_mutex); return -ENODEV; } @@ -1649,6 +1672,8 @@ static int amvdec_h264mvc_remove(struct platform_device *pdev) #ifdef DEBUG_SKIP pr_info("view_total = %ld, dropped %ld\n", view_total, view_dropped); #endif + vfree(buffer_spec0); + buffer_spec0 = NULL; kfree(gvs); gvs = NULL; @@ -1734,6 +1759,9 @@ MODULE_PARM_DESC(stat, "\n amvdec_h264mvc stat\n"); module_param(dbg_mode, uint, 0664); MODULE_PARM_DESC(dbg_mode, "\n amvdec_h264mvc dbg mode\n"); +module_param(dynamic_buf_num_margin, uint, 0664); +MODULE_PARM_DESC(dynamic_buf_num_margin, "\n amvdec_h264mvc dynamic_buf_num_margin\n"); + module_param(view_mode, uint, 0664); MODULE_PARM_DESC(view_mode, "\n amvdec_h264mvc view mode\n"); diff --git a/drivers/frame_provider/decoder/h264_multi/vmh264.c b/drivers/frame_provider/decoder/h264_multi/vmh264.c index 35d67ad..c2e0e91 100644 --- a/drivers/frame_provider/decoder/h264_multi/vmh264.c +++ b/drivers/frame_provider/decoder/h264_multi/vmh264.c @@ -61,6 +61,7 @@ #include "../../../common/chips/decoder_cpu_ver_info.h" #include "../utils/vdec_v4l2_buffer_ops.h" #include <linux/crc32.h> +#include <media/v4l2-mem2mem.h> #undef pr_info #define pr_info printk @@ -117,6 +118,7 @@ #define H264_MMU #define VIDEO_SIGNAL_TYPE_AVAILABLE_MASK 0x20000000 +#define INVALID_IDX -1 /* Invalid buffer index.*/ static int mmu_enable; /*mmu do not support mbaff*/ @@ -158,6 +160,8 @@ static u32 run_ready_display_q_num; static u32 run_ready_max_buf_num = 0xff; #endif +static u32 run_ready_min_buf_num = 2; + #define VDEC_ASSIST_CANVAS_BLK32 0x5 @@ -845,6 +849,7 @@ struct vdec_h264_hw_s { bool new_iframe_flag; bool ref_err_flush_dpb_flag; unsigned int first_i_policy; + u32 reorder_dpb_size_margin; }; static u32 again_threshold; @@ -854,7 +859,7 @@ static void dump_bufspec(struct vdec_h264_hw_s *hw, const char *caller); static void h264_reconfig(struct vdec_h264_hw_s *hw); static void h264_reset_bufmgr(struct vdec_s *vdec); -static void vh264_local_init(struct vdec_h264_hw_s *hw); +static void vh264_local_init(struct vdec_h264_hw_s *hw, bool is_reset); static int vh264_hw_ctx_restore(struct vdec_h264_hw_s *hw); static int vh264_stop(struct vdec_h264_hw_s *hw); static s32 vh264_init(struct vdec_h264_hw_s *hw); @@ -947,11 +952,10 @@ static int hevc_alloc_mmu(struct vdec_h264_hw_s *hw, int pic_idx, } return decoder_mmu_box_alloc_idx( - hw->mmu_box, - cur_buf_idx, - cur_mmu_4k_number, - mmu_index_adr); - + hw->mmu_box, + cur_buf_idx, + cur_mmu_4k_number, + mmu_index_adr); } static int compute_losless_comp_body_size(int width, @@ -1061,7 +1065,7 @@ static void hevc_mcr_config_canv2axitbl(struct vdec_h264_hw_s *hw, int restore) int num_buff = hw->dpb.mDPB.size; int dw_size = 0; u32 dw_buffer_size_u_v_h; - u32 blkmode = mem_map_mode; + u32 blkmode = hw->canvas_mode; int dw_mode = hw->double_write_mode; canvas_addr = ANC0_CANVAS_ADDR; @@ -1115,7 +1119,7 @@ static void hevc_mcr_config_canv2axitbl(struct vdec_h264_hw_s *hw, int restore) canvas_h = hw->frame_height / get_double_write_ratio(hw); - if (mem_map_mode == 0) + if (hw->canvas_mode == 0) canvas_w = ALIGN(canvas_w, 32); else canvas_w = ALIGN(canvas_w, 64); @@ -1315,7 +1319,7 @@ static void hevc_mcr_sao_global_hw_init(struct vdec_h264_hw_s *hw, #endif data32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG); data32 &= (~0x30); - data32 |= (mem_map_mode << 4); + data32 |= (hw->canvas_mode << 4); WRITE_VREG(HEVCD_IPP_AXIIF_CONFIG, data32); WRITE_VREG(HEVCD_MPP_DECOMP_CTL3, @@ -1360,9 +1364,9 @@ static void hevc_mcr_sao_global_hw_init(struct vdec_h264_hw_s *hw, data32 |= endian; /* Big-Endian per 64-bit */ if (hw->mmu_enable && dw_mode) - data32 |= ((mem_map_mode << 12)); + data32 |= ((hw->canvas_mode << 12)); else - data32 |= ((mem_map_mode << 12)|2); + data32 |= ((hw->canvas_mode << 12)|2); WRITE_VREG(HEVC_SAO_CTRL1, data32); @@ -1603,10 +1607,36 @@ static void buf_spec_init(struct vdec_h264_hw_s *hw) int i; unsigned long flags; spin_lock_irqsave(&hw->bufspec_lock, flags); + + for (i = 0; i < VF_POOL_SIZE; i++) { + struct vframe_s *vf = &hw->vfpool[hw->cur_pool][i]; + u32 ref_idx = BUFSPEC_INDEX(vf->index); + if ((vf->index != -1) && + (hw->buffer_spec[ref_idx].vf_ref == 0) && + (hw->buffer_spec[ref_idx].used != -1)) { + vf->index = -1; + } + } + + hw->cur_pool++; + if (hw->cur_pool >= VF_POOL_NUM) + hw->cur_pool = 0; + + for (i = 0; i < VF_POOL_SIZE; i++) { + struct vframe_s *vf = &hw->vfpool[hw->cur_pool][i]; + u32 ref_idx = BUFSPEC_INDEX(vf->index); + if ((vf->index != -1) && + (hw->buffer_spec[ref_idx].vf_ref == 0) && + (hw->buffer_spec[ref_idx].used != -1)) { + vf->index = -1; + } + } + for (i = 0; i < BUFSPEC_POOL_SIZE; i++) { hw->buffer_spec[i].used = -1; hw->buffer_spec[i].canvas_pos = -1; } + if (dpb_is_debug(DECODE_ID(hw), PRINT_FLAG_DUMP_BUFSPEC)) dump_bufspec(hw, __func__); @@ -1654,7 +1684,7 @@ static int alloc_one_buf_spec(struct vdec_h264_hw_s *hw, int i) if (IS_VDEC_DW(hw) == 1) buf_size += (hw->mb_total << 7) + (hw->mb_total << 6); else if (IS_VDEC_DW(hw) == 2) - buf_size += (hw->mb_total << 6) + (hw->mb_total << 6); + buf_size += (hw->mb_total << 6) + (hw->mb_total << 5); #endif if (hw->buffer_spec[i].cma_alloc_addr) return 0; @@ -1798,7 +1828,7 @@ static int alloc_one_buf_spec_from_queue(struct vdec_h264_hw_s *hw, int idx) (hw->mb_total << 8) + (hw->mb_total << 7)); ret = vdec_v4l_get_buffer(hw->v4l2_ctx, &fb); - if (ret) { + if (ret < 0) { dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, "[%d] get fb fail.\n", ctx->id); return ret; @@ -1837,7 +1867,7 @@ static int alloc_one_buf_spec_from_queue(struct vdec_h264_hw_s *hw, int idx) y_canvas_cfg->phy_addr = y_addr; y_canvas_cfg->width = hw->mb_width << 4; y_canvas_cfg->height = hw->mb_height << 4; - y_canvas_cfg->block_mode = CANVAS_BLKMODE_LINEAR; + y_canvas_cfg->block_mode = hw->canvas_mode; //fb->m.mem[0].bytes_used = y_canvas_cfg->width * y_canvas_cfg->height; dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, "[%d] %s(), y_w: %d, y_h: %d\n", ctx->id, __func__, @@ -1846,7 +1876,7 @@ static int alloc_one_buf_spec_from_queue(struct vdec_h264_hw_s *hw, int idx) c_canvas_cfg->phy_addr = c_addr; c_canvas_cfg->width = hw->mb_width << 4; c_canvas_cfg->height = hw->mb_height << 3; - c_canvas_cfg->block_mode = CANVAS_BLKMODE_LINEAR; + c_canvas_cfg->block_mode = hw->canvas_mode; //fb->m.mem[1].bytes_used = c_canvas_cfg->width * c_canvas_cfg->height; dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, "[%d] %s(), c_w: %d, c_h: %d\n", ctx->id, __func__, @@ -1860,24 +1890,18 @@ static int alloc_one_buf_spec_from_queue(struct vdec_h264_hw_s *hw, int idx) static void config_decode_canvas(struct vdec_h264_hw_s *hw, int i) { - struct aml_vcodec_ctx * v4l2_ctx = hw->v4l2_ctx; - int blkmode = CANVAS_BLKMODE_32X32; + int blkmode = hw->canvas_mode; int endian = 0; - if (hw->canvas_mode == CANVAS_BLKMODE_LINEAR) { - blkmode = CANVAS_BLKMODE_LINEAR; + if (blkmode == CANVAS_BLKMODE_LINEAR) { if ((h264_debug_flag & IGNORE_PARAM_FROM_CONFIG) == 0) endian = 7; else endian = 0; } - if (hw->is_used_v4l) { - blkmode = CANVAS_BLKMODE_LINEAR; - if (v4l2_ctx->ada_ctx->vfm_path - != FRAME_BASE_PATH_V4L_VIDEO) + if (hw->is_used_v4l) endian = 7; - } canvas_config_ex(hw->buffer_spec[i]. y_canvas_index, @@ -1990,7 +2014,7 @@ static void config_decode_canvas(struct vdec_h264_hw_s *hw, int i) static void config_decode_canvas_ex(struct vdec_h264_hw_s *hw, int i) { - u32 blkmode = mem_map_mode; + u32 blkmode = hw->canvas_mode; int canvas_w; int canvas_h; @@ -1999,7 +2023,7 @@ static void config_decode_canvas_ex(struct vdec_h264_hw_s *hw, int i) canvas_h = hw->frame_height / get_double_write_ratio(hw); - if (mem_map_mode == 0) + if (hw->canvas_mode == 0) canvas_w = ALIGN(canvas_w, 32); else canvas_w = ALIGN(canvas_w, 64); @@ -2024,6 +2048,55 @@ static void config_decode_canvas_ex(struct vdec_h264_hw_s *hw, int i) 7); } +static int v4l_get_free_buf_idx(struct vdec_s *vdec) +{ + struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; + struct aml_vcodec_ctx * v4l = hw->v4l2_ctx; + struct v4l_buff_pool *pool = &v4l->cap_pool; + struct buffer_spec_s *pic = NULL; + int i, idx = INVALID_IDX; + ulong flags; + + spin_lock_irqsave(&hw->bufspec_lock, flags); + for (i = 0; i < pool->in; ++i) { + u32 state = (pool->seq[i] >> 16); + u32 index = (pool->seq[i] & 0xffff); + + switch (state) { + case V4L_CAP_BUFF_IN_DEC: + pic = &hw->buffer_spec[i]; + if ((pic->vf_ref == 0) && + (pic->used == 0) && + pic->cma_alloc_addr) { + idx = i; + } + break; + case V4L_CAP_BUFF_IN_M2M: + pic = &hw->buffer_spec[index]; + if (!alloc_one_buf_spec_from_queue(hw, index)) { + config_decode_canvas(hw, index); + idx = index; + } + break; + default: + pr_err("v4l buffer state err %d.\n", state); + break; + } + + if (idx != INVALID_IDX) { + pic->used = 1; + break; + } + } + spin_unlock_irqrestore(&hw->bufspec_lock, flags); + + if (idx < 0) { + dpb_print(DECODE_ID(hw), 0, "%s fail\n", __func__); + vmh264_dump_state(vdec); + } + + return idx; +} int get_free_buf_idx(struct vdec_s *vdec) { @@ -2034,23 +2107,18 @@ int get_free_buf_idx(struct vdec_s *vdec) int buf_total = BUFSPEC_POOL_SIZE; if (hw->is_used_v4l) - buf_total = hw->dpb.mDPB.size; + return v4l_get_free_buf_idx(vdec); spin_lock_irqsave(&hw->bufspec_lock, flags); /*hw->start_search_pos = 0;*/ for (i = hw->start_search_pos; i < buf_total; i++) { if (hw->mmu_enable) addr = hw->buffer_spec[i].alloc_header_addr; - else { + else addr = hw->buffer_spec[i].cma_alloc_addr; - if (hw->is_used_v4l && !addr) { - if (!alloc_one_buf_spec_from_queue(hw, i)) { - config_decode_canvas(hw, i); - addr = hw->buffer_spec[i].cma_alloc_addr; - } - } - } - if (hw->buffer_spec[i].used == 0 && addr) { + + if (hw->buffer_spec[i].vf_ref == 0 && + hw->buffer_spec[i].used == 0 && addr) { hw->buffer_spec[i].used = 1; hw->start_search_pos = i+1; index = i; @@ -2061,16 +2129,11 @@ int get_free_buf_idx(struct vdec_s *vdec) for (i = 0; i < hw->start_search_pos; i++) { if (hw->mmu_enable) addr = hw->buffer_spec[i].alloc_header_addr; - else { + else addr = hw->buffer_spec[i].cma_alloc_addr; - if (hw->is_used_v4l && !addr) { - if (!alloc_one_buf_spec_from_queue(hw, i)) { - config_decode_canvas(hw, i); - addr = hw->buffer_spec[i].cma_alloc_addr; - } - } - } - if (hw->buffer_spec[i].used == 0 && addr) { + + if (hw->buffer_spec[i].vf_ref == 0 && + hw->buffer_spec[i].used == 0 && addr) { hw->buffer_spec[i].used = 1; hw->start_search_pos = i+1; index = i; @@ -2325,16 +2388,35 @@ unsigned char have_free_buf_spec(struct vdec_s *vdec) int i; unsigned long addr; struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; + struct aml_vcodec_ctx * v4l = hw->v4l2_ctx; int canvas_pos_min = BUFSPEC_POOL_SIZE; int index = -1; int ret = 0; int allocated_count = 0; + + if (hw->is_used_v4l) { + for (i = 0; i < hw->dpb.mDPB.size; i++) { + if (hw->buffer_spec[i].used == 0 && + hw->buffer_spec[i].vf_ref == 0 && + hw->buffer_spec[i].cma_alloc_addr) { + return 1; + } + } + + if (v4l2_m2m_num_dst_bufs_ready(v4l->m2m_ctx) + >= run_ready_min_buf_num) + return 1; + + return 0; + } + for (i = 0; i < BUFSPEC_POOL_SIZE; i++) { if (hw->mmu_enable) addr = hw->buffer_spec[i].alloc_header_addr; else addr = hw->buffer_spec[i].cma_alloc_addr; - if (hw->buffer_spec[i].used == 0) { + if (hw->buffer_spec[i].used == 0 && + hw->buffer_spec[i].vf_ref == 0) { if (addr) return 1; @@ -2351,13 +2433,12 @@ unsigned char have_free_buf_spec(struct vdec_s *vdec) dealloc_buf_specs(hw, 0); if (max_alloc_buf_count == 0 || allocated_count < max_alloc_buf_count) { - if (hw->is_used_v4l) - ret = 1; - else if (alloc_one_buf_spec(hw, index) >= 0) + if (alloc_one_buf_spec(hw, index) >= 0) ret = 1; } mutex_unlock(&vmh264_mutex); } + return ret; } @@ -2611,18 +2692,6 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) if (hw->is_used_v4l) { vf->v4l_mem_handle = hw->buffer_spec[buffer_index].cma_alloc_addr; - if (hw->mmu_enable) { - if (vdec_v4l_binding_fd_and_vf(vf->v4l_mem_handle, vf) < 0) { - dpb_print(DECODE_ID(hw), - PRINT_FLAG_V4L_DETAIL, - "v4l: binding vf fail.\n"); - return -1; - } - } - dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, - "[%d] %s(), v4l mem handle: 0x%x\n", - ((struct aml_vcodec_ctx *)(hw->v4l2_ctx))->id, - __func__, vf->v4l_mem_handle); } if (hw->mmu_enable) { @@ -2759,26 +2828,31 @@ int notify_v4l_eos(struct vdec_s *vdec) { struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)(hw->v4l2_ctx); - struct vframe_s *vf = NULL; + struct vframe_s *vf = &hw->vframe_dummy; struct vdec_v4l2_buffer *fb = NULL; + int index = INVALID_IDX; + ulong expires; if (hw->is_used_v4l && hw->eos) { - if (kfifo_get(&hw->newframe_q, &vf) == 0 || vf == NULL) { - dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR, - "%s fatal error, no available buffer slot.\n", - __func__); - return -1; + expires = jiffies + msecs_to_jiffies(2000); + while (INVALID_IDX == (index = v4l_get_free_buf_idx(vdec))) { + if (time_after(jiffies, expires) || + v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx)) + break; } - if (vdec_v4l_get_buffer(hw->v4l2_ctx, &fb)) { - pr_err("[%d] get fb fail.\n", ctx->id); - return -1; + if (index == INVALID_IDX) { + if (vdec_v4l_get_buffer(hw->v4l2_ctx, &fb) < 0) { + pr_err("[%d] EOS get free buff fail.\n", ctx->id); + return -1; + } } - vf->type |= VIDTYPE_V4L_EOS; - vf->timestamp = ULONG_MAX; - vf->v4l_mem_handle = (unsigned long)fb; - vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L; + vf->type |= VIDTYPE_V4L_EOS; + vf->timestamp = ULONG_MAX; + vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L; + vf->v4l_mem_handle = (index == INVALID_IDX) ? (ulong)fb : + hw->buffer_spec[index].cma_alloc_addr; kfifo_put(&hw->display_q, (const struct vframe_s *)vf); @@ -3775,6 +3849,7 @@ static struct vframe_s *vh264_vf_get(void *op_arg) = frame_interval; } hw->last_frame_time = time; + vf->index_disp = hw->vf_get_count; hw->vf_get_count++; if (kfifo_peek(&hw->display_q, &next_vf)) { vf->next_vf_pts_valid = true; @@ -3791,6 +3866,7 @@ static void vh264_vf_put(struct vframe_s *vf, void *op_arg) { struct vdec_s *vdec = op_arg; struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; + unsigned long flags; int buf_spec_num; int frame_index; @@ -3815,6 +3891,7 @@ static void vh264_vf_put(struct vframe_s *vf, void *op_arg) } /*get_buf_spec_idx_by_canvas_config(hw, &vf->canvas0_config[0]);*/ + spin_lock_irqsave(&hw->bufspec_lock, flags); if (hw->buffer_spec[buf_spec_num].used == 2) { struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, @@ -3828,13 +3905,11 @@ static void vh264_vf_put(struct vframe_s *vf, void *op_arg) if (hw->buffer_spec[buf_spec_num].vf_ref <= 0) set_frame_output_flag(&hw->dpb, frame_index); } else { - unsigned long flags; dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, "%s %p isolated vf, buf_spec_num %d used %d vf_ref %d\n", __func__, vf, buf_spec_num, hw->buffer_spec[buf_spec_num].used, hw->buffer_spec[buf_spec_num].vf_ref); - spin_lock_irqsave(&hw->bufspec_lock, flags); hw->buffer_spec[buf_spec_num].vf_ref--; if (hw->buffer_spec[buf_spec_num].vf_ref <= 0) { if (hw->buffer_spec[buf_spec_num].used == 3) @@ -3842,12 +3917,12 @@ static void vh264_vf_put(struct vframe_s *vf, void *op_arg) else if (hw->buffer_spec[buf_spec_num].used == 5) hw->buffer_spec[buf_spec_num].used = 0; } - spin_unlock_irqrestore(&hw->bufspec_lock, flags); if (dpb_is_debug(DECODE_ID(hw), PRINT_FLAG_DUMP_BUFSPEC)) dump_bufspec(hw, __func__); } + spin_unlock_irqrestore(&hw->bufspec_lock, flags); hw->vf_put_count++; kfifo_put(&hw->newframe_q, (const struct vframe_s *)vf); @@ -3866,7 +3941,13 @@ static int vh264_event_cb(int type, void *data, void *op_arg) if (type & VFRAME_EVENT_RECEIVER_GET_AUX_DATA) { struct provider_aux_req_s *req = (struct provider_aux_req_s *)data; - int buf_spec_num = BUFSPEC_INDEX(req->vf->index); + int buf_spec_num; + + if (!req->vf) { + req->aux_size = hw->vf_put_count; + return 0; + } + buf_spec_num = BUFSPEC_INDEX(req->vf->index); spin_lock_irqsave(&hw->lock, flags); req->aux_buf = NULL; req->aux_size = 0; @@ -3905,6 +3986,21 @@ static void set_frame_info(struct vdec_h264_hw_s *hw, struct vframe_s *vf, "%s (%d,%d) dur %d, vf %p, index %d\n", __func__, hw->frame_width, hw->frame_height, hw->frame_dur, vf, index); + /* signal_type */ + if (hw->video_signal_from_vui & VIDEO_SIGNAL_TYPE_AVAILABLE_MASK) { + vf->signal_type = hw->video_signal_from_vui; + if (hw->is_used_v4l) { + struct aml_vdec_hdr_infos hdr; + struct aml_vcodec_ctx *ctx = + (struct aml_vcodec_ctx *)(hw->v4l2_ctx); + + memset(&hdr, 0, sizeof(hdr)); + hdr.signal_type = hw->video_signal_from_vui; + vdec_v4l_set_hdr_infos(ctx, &hdr); + } + } else + vf->signal_type = 0; + vf->width = hw->frame_width; vf->height = hw->frame_height; if (force_rate) { @@ -3918,8 +4014,10 @@ static void set_frame_info(struct vdec_h264_hw_s *hw, struct vframe_s *vf, (min(hw->h264_ar, (u32) DISP_RATIO_ASPECT_RATIO_MAX)) << DISP_RATIO_ASPECT_RATIO_BIT; vf->orientation = hw->vh264_rotation; + if (hw->mmu_enable) return; + vf->canvas0Addr = vf->canvas1Addr = -1; #ifdef NV21 vf->plane_num = 2; @@ -3945,12 +4043,6 @@ static void set_frame_info(struct vdec_h264_hw_s *hw, struct vframe_s *vf, #ifndef NV21 vf->canvas1_config[2] = p_canvas_config[2]; #endif - /* signal_type */ - if (hw->video_signal_from_vui & VIDEO_SIGNAL_TYPE_AVAILABLE_MASK) - vf->signal_type = hw->video_signal_from_vui; - else - vf->signal_type = 0; - } static void get_picture_qos_info(struct StorablePicture *picture) @@ -4413,8 +4505,9 @@ static int get_max_dec_frame_buf_size(int level_idc, size /= pic_size; size = size + 1; /* need one more buffer */ - if (max_reference_frame_num < size) + if (max_reference_frame_num > size) size = max_reference_frame_num; + size = imin(size, 16); return size; } @@ -4454,7 +4547,7 @@ static int vh264_set_params(struct vdec_h264_hw_s *hw, unsigned int chroma_format_idc, chroma444; unsigned int crop_infor, crop_bottom, crop_right; unsigned int used_reorder_dpb_size_margin - = reorder_dpb_size_margin; + = hw->reorder_dpb_size_margin; u8 *colocate_vaddr = NULL; #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION @@ -4633,7 +4726,7 @@ static int vh264_set_params(struct vdec_h264_hw_s *hw, if (hw->is_used_v4l) { if (i != -1) { - pr_info("alloc the buf of v4l when it is about to decoding.\n"); + pr_info("v4l: delay alloc the buffer.\n"); } } else { if ((i != -1) && alloc_one_buf_spec(hw, i) >= 0) @@ -4725,7 +4818,7 @@ static int vh264_set_params(struct vdec_h264_hw_s *hw, i = get_buf_spec_by_canvas_pos(hw, j); if (hw->is_used_v4l) { - pr_info("alloc the buf of v4l when it is about to decoding.\n"); + pr_info("v4l: delay alloc the buffer.\n"); break; } else if (alloc_one_buf_spec(hw, i) < 0) break; @@ -5090,6 +5183,8 @@ static bool is_buffer_available(struct vdec_s *vdec) if (hw->reset_bufmgr_flag == 1) buffer_available = 1; + else if (hw->is_used_v4l) + buffer_available = have_free_buf_spec(vdec); } return buffer_available; @@ -5581,6 +5676,10 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq) val(p_H264_Dpb->dpb_param.dpb.top_field_pic_order_cnt)); I_flag = (p_H264_Dpb->dpb_param.l.data[SLICE_TYPE] == I_Slice) ? I_FLAG : 0; + + if ((hw->i_only & 0x2) && (I_flag & I_FLAG)) + flush_dpb(p_H264_Dpb); + if ((hw->i_only & 0x2) && (!(I_flag & I_FLAG)) && (p_H264_Dpb->mSlice.structure == FRAME)) { hw->data_flag = NULL_FLAG; @@ -5607,7 +5706,8 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq) true : false; } - if (!field_pic_flag && ((p_H264_Dpb->mSPS.profile_idc == BASELINE) || + if (!field_pic_flag && (((p_H264_Dpb->mSPS.profile_idc == BASELINE) && + (p_H264_Dpb->reorder_pic_num < 2)) || (((unsigned long)(hw->vh264_amstream_dec_info .param)) & 0x8))) { p_H264_Dpb->fast_output_enable = @@ -5698,7 +5798,7 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq) } else hw->reflist_error_count = 0; } - if ((error_proc_policy & 0x800) + if ((error_proc_policy & 0x800) && (!(hw->i_only & 0x2)) && p_H264_Dpb->dpb_error_flag != 0) { dpb_print(DECODE_ID(hw), 0, "dpb error %d\n", @@ -5748,6 +5848,7 @@ pic_done_proc: reset_process_time(hw); if (input_frame_based(vdec) && + (!(hw->i_only & 0x2)) && frmbase_cont_bitlevel != 0 && READ_VREG(VIFF_BIT_CNT) > frmbase_cont_bitlevel) { @@ -5822,6 +5923,7 @@ pic_done_proc: } mutex_unlock(&hw->chunks_mutex); + check_decoded_pic_error(hw); #ifdef ERROR_HANDLE_TEST if ((hw->data_flag & ERROR_FLAG) @@ -6338,7 +6440,7 @@ static void vmh264_dump_state(struct vdec_s *vdec) } dpb_print(DECODE_ID(hw), 0, - "%s, newq(%d/%d), dispq(%d/%d) vf prepare/get/put (%d/%d/%d), free_spec(%d), initdon(%d), used_size(%d/%d), unused_fr_dpb(%d) fast_output_enable %x\n", + "%s, newq(%d/%d), dispq(%d/%d) vf prepare/get/put (%d/%d/%d), free_spec(%d), initdon(%d), used_size(%d/%d), unused_fr_dpb(%d) fast_output_enable %x \n", __func__, kfifo_len(&hw->newframe_q), VF_POOL_SIZE, @@ -6734,7 +6836,7 @@ static int vmh264_set_trickmode(struct vdec_s *vdec, unsigned long trickmode) } static unsigned char amvdec_enable_flag; -static void vh264_local_init(struct vdec_h264_hw_s *hw) +static void vh264_local_init(struct vdec_h264_hw_s *hw, bool is_reset) { int i; hw->init_flag = 0; @@ -6785,9 +6887,6 @@ static void vh264_local_init(struct vdec_h264_hw_s *hw) hw->first_i_policy = first_i_policy; - if (hw->is_used_v4l) - mem_map_mode = CANVAS_BLKMODE_LINEAR; - pr_info("H264 sysinfo: %dx%d duration=%d, pts_outside=%d\n", hw->frame_width, hw->frame_height, hw->frame_dur, hw->pts_outside); pr_debug("sync_outside=%d, use_idr_framerate=%d, is_used_v4l: %d\n", @@ -6808,14 +6907,16 @@ static void vh264_local_init(struct vdec_h264_hw_s *hw) else if ((unsigned long) hw->vh264_amstream_dec_info.param & 0x20) hw->send_error_frame_flag = 0; /*Don't display mark err frames*/ - INIT_KFIFO(hw->display_q); - INIT_KFIFO(hw->newframe_q); + if (!is_reset) { + INIT_KFIFO(hw->display_q); + INIT_KFIFO(hw->newframe_q); - for (i = 0; i < VF_POOL_SIZE; i++) { - const struct vframe_s *vf = &(hw->vfpool[hw->cur_pool][i]); - hw->vfpool[hw->cur_pool][i].index = -1; /* VF_BUF_NUM; */ - hw->vfpool[hw->cur_pool][i].bufWidth = 1920; - kfifo_put(&hw->newframe_q, vf); + for (i = 0; i < VF_POOL_SIZE; i++) { + const struct vframe_s *vf = &(hw->vfpool[hw->cur_pool][i]); + hw->vfpool[hw->cur_pool][i].index = -1; /* VF_BUF_NUM; */ + hw->vfpool[hw->cur_pool][i].bufWidth = 1920; + kfifo_put(&hw->newframe_q, vf); + } } hw->duration_from_pts_done = 0; @@ -6853,7 +6954,7 @@ static s32 vh264_init(struct vdec_h264_hw_s *hw) hw->stat |= STAT_ISR_REG; mutex_init(&hw->chunks_mutex); - vh264_local_init(hw); + vh264_local_init(hw, false); INIT_WORK(&hw->work, vh264_work); INIT_WORK(&hw->notify_work, vh264_notify_work); INIT_WORK(&hw->timeout_work, vh264_timeout_work); @@ -7822,15 +7923,15 @@ static void vh264_work_implement(struct vdec_h264_hw_s *hw, (struct aml_vcodec_ctx *)(hw->v4l2_ctx); if (ctx->param_sets_from_ucode && !hw->v4l_params_parsed) { - struct aml_vdec_pic_infos info; + struct aml_vdec_ps_infos ps; - info.visible_width = hw->frame_width; - info.visible_height = hw->frame_height; - info.coded_width = ALIGN(hw->frame_width, 64); - info.coded_height = ALIGN(hw->frame_height, 64); - info.dpb_size = hw->dpb.mDPB.size; + ps.visible_width = hw->frame_width; + ps.visible_height = hw->frame_height; + ps.coded_width = ALIGN(hw->frame_width, 64); + ps.coded_height = ALIGN(hw->frame_height, 64); + ps.dpb_size = hw->dpb.mDPB.size; hw->v4l_params_parsed = true; - vdec_v4l_set_pic_infos(ctx, &info); + vdec_v4l_set_ps_infos(ctx, &ps); } } @@ -8190,18 +8291,23 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) get_used_buf_count(hw) >= run_ready_max_buf_num) ret = 0; + } +#endif + if (hw->is_used_v4l) { + struct aml_vcodec_ctx *ctx = + (struct aml_vcodec_ctx *)(hw->v4l2_ctx); - if (hw->is_used_v4l) { - struct aml_vcodec_ctx *ctx = - (struct aml_vcodec_ctx *)(hw->v4l2_ctx); - - if (ctx->param_sets_from_ucode && - !ctx->v4l_codec_ready && - hw->v4l_params_parsed) - ret = 0; /*the params has parsed.*/ + if (ctx->param_sets_from_ucode && + !ctx->v4l_codec_ready && + hw->v4l_params_parsed) { + ret = 0; /*the params has parsed.*/ + } else if (!ctx->v4l_codec_dpb_ready) { + if (v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) < + run_ready_min_buf_num) + ret = 0; } } -#endif + if (ret) not_run_ready[DECODE_ID(hw)] = 0; else @@ -8465,6 +8571,25 @@ static void run(struct vdec_s *vdec, unsigned long mask, hw->init_flag = 1; } +static void clear_refer_bufs(struct vdec_h264_hw_s *hw) +{ + int i; + + mutex_lock(&vmh264_mutex); + dealloc_buf_specs(hw, 1); + mutex_unlock(&vmh264_mutex); + + INIT_KFIFO(hw->display_q); + INIT_KFIFO(hw->newframe_q); + + for (i = 0; i < VF_POOL_SIZE; i++) { + const struct vframe_s *vf = &(hw->vfpool[hw->cur_pool][i]); + hw->vfpool[hw->cur_pool][i].index = -1; /* VF_BUF_NUM; */ + hw->vfpool[hw->cur_pool][i].bufWidth = 1920; + kfifo_put(&hw->newframe_q, vf); + } +} + static void reset(struct vdec_s *vdec) { struct vdec_h264_hw_s *hw = @@ -8486,6 +8611,8 @@ static void reset(struct vdec_s *vdec) hw->eos = 0; hw->decode_pic_count = 0; hw->dec_result = DEC_RESULT_NONE; + + clear_refer_bufs(hw); reset_process_time(hw); h264_reset_bufmgr(vdec); @@ -8497,6 +8624,7 @@ static void h264_reconfig(struct vdec_h264_hw_s *hw) int i; unsigned long flags; struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; + struct vdec_s *vdec = hw_to_vdec(hw); dpb_print(DECODE_ID(hw), 0, "%s\n", __func__); /* after calling flush_dpb() and bufmgr_h264_remove_unused_frame(), @@ -8520,6 +8648,24 @@ static void h264_reconfig(struct vdec_h264_hw_s *hw) } spin_lock_irqsave(&hw->bufspec_lock, flags); for (i = 0; i < BUFSPEC_POOL_SIZE; i++) { + if (vdec->parallel_dec == 1) { + vdec->free_canvas_ex(hw->buffer_spec[i].y_canvas_index, vdec->id); + vdec->free_canvas_ex(hw->buffer_spec[i].u_canvas_index, vdec->id); + vdec->free_canvas_ex(hw->buffer_spec[i].v_canvas_index, vdec->id); + hw->buffer_spec[i].y_canvas_index = -1; + hw->buffer_spec[i].u_canvas_index = -1; + hw->buffer_spec[i].v_canvas_index = -1; +#ifdef VDEC_DW + if (IS_VDEC_DW(hw)) { + vdec->free_canvas_ex(hw->buffer_spec[i].vdec_dw_y_canvas_index, vdec->id); + vdec->free_canvas_ex(hw->buffer_spec[i].vdec_dw_u_canvas_index, vdec->id); + vdec->free_canvas_ex(hw->buffer_spec[i].vdec_dw_v_canvas_index, vdec->id); + hw->buffer_spec[i].vdec_dw_y_canvas_index = -1; + hw->buffer_spec[i].vdec_dw_u_canvas_index = -1; + hw->buffer_spec[i].vdec_dw_v_canvas_index = -1; +#endif + } + } /*make sure buffers not put back to bufmgr when vf_put is called*/ if (hw->buffer_spec[i].used == 2) @@ -8545,7 +8691,6 @@ static void h264_reconfig(struct vdec_h264_hw_s *hw) if (dpb_is_debug(DECODE_ID(hw), PRINT_FLAG_DUMP_BUFSPEC)) dump_bufspec(hw, "after h264_reconfig"); - } #ifdef ERROR_HANDLE_TEST @@ -8568,7 +8713,6 @@ static void h264_clear_dpb(struct vdec_h264_hw_s *hw) static void h264_reset_bufmgr(struct vdec_s *vdec) { - int i; ulong timeout; struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; #if 0 @@ -8634,32 +8778,14 @@ static void h264_reset_bufmgr(struct vdec_s *vdec) schedule(); } - for (i = 0; i < VF_POOL_SIZE; i++) - hw->vfpool[hw->cur_pool][i].index = -1; /* VF_BUF_NUM; */ - - hw->cur_pool++; - if (hw->cur_pool >= VF_POOL_NUM) - hw->cur_pool = 0; - - for (i = 0; i < VF_POOL_SIZE; i++) - hw->vfpool[hw->cur_pool][i].index = -1; /* VF_BUF_NUM; */ - - vf_notify_receiver(vdec->vf_provider_name, VFRAME_EVENT_PROVIDER_RESET, NULL); buf_spec_init(hw); - vh264_local_init(hw); + vh264_local_init(hw, true); /*hw->decode_pic_count = 0; hw->seq_info2 = 0;*/ - if (hw->is_used_v4l) { - mutex_lock(&vmh264_mutex); - /* detach relationship with v4l buffs.*/ - dealloc_buf_specs(hw, 1); - mutex_unlock(&vmh264_mutex); - } - if (vh264_set_params(hw, hw->cfg_param1, hw->cfg_param2, @@ -8750,11 +8876,6 @@ static int ammvdec_h264_probe(struct platform_device *pdev) /* the ctx from v4l2 driver. */ hw->v4l2_ctx = pdata->private; - if ((h264_debug_flag & IGNORE_PARAM_FROM_CONFIG) == 0) - hw->canvas_mode = pdata->canvas_mode; - else - hw->canvas_mode = mem_map_mode; - platform_set_drvdata(pdev, pdata); hw->mmu_enable = 0; @@ -8765,16 +8886,6 @@ static int ammvdec_h264_probe(struct platform_device *pdev) if (pdata->sys_info) hw->vh264_amstream_dec_info = *pdata->sys_info; - hw->is_used_v4l = (((unsigned long) - hw->vh264_amstream_dec_info.param & 0x80) >> 7); - if (hw->is_used_v4l) { - hw->mmu_enable = (((unsigned long) - hw->vh264_amstream_dec_info.param & 0x100) >> 8); - dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, - "%s v4: enable mmu %d.\n", - __func__, hw->mmu_enable); - } - if (force_enable_mmu && pdata->sys_info && (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_TXLX) && (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_GXLX) && @@ -8802,9 +8913,32 @@ static int ammvdec_h264_probe(struct platform_device *pdev) hw->double_write_mode = config_val; else hw->double_write_mode = double_write_mode; + + if (get_config_int(pdata->config, + "parm_v4l_codec_enable", + &config_val) == 0) + hw->is_used_v4l = config_val; + + if (get_config_int(pdata->config, + "parm_v4l_buffer_margin", + &config_val) == 0) + hw->reorder_dpb_size_margin = config_val; + + if (get_config_int(pdata->config, + "parm_v4l_canvas_mem_mode", + &config_val) == 0) + hw->canvas_mode = config_val; } else hw->double_write_mode = double_write_mode; + if (!hw->is_used_v4l) { + hw->reorder_dpb_size_margin = reorder_dpb_size_margin; + hw->canvas_mode = mem_map_mode; + + if ((h264_debug_flag & IGNORE_PARAM_FROM_CONFIG) == 0) + hw->canvas_mode = pdata->canvas_mode; + } + if (hw->mmu_enable) hw->double_write_mode &= 0xffff; diff --git a/drivers/frame_provider/decoder/h265/vh265.c b/drivers/frame_provider/decoder/h265/vh265.c index 37e6969..170cc22 100644 --- a/drivers/frame_provider/decoder/h265/vh265.c +++ b/drivers/frame_provider/decoder/h265/vh265.c @@ -47,6 +47,7 @@ #include "../utils/firmware.h" #include "../../../common/chips/decoder_cpu_ver_info.h" #include "../utils/vdec_v4l2_buffer_ops.h" +#include <media/v4l2-mem2mem.h> #define CONSTRAIN_MAX_BUF_NUM @@ -128,6 +129,7 @@ #define IS_4K_SIZE(w, h) (((w) * (h)) > (1920*1088)) #define SEI_UserDataITU_T_T35 4 +#define INVALID_IDX -1 /* Invalid buffer index.*/ static struct semaphore h265_sema; @@ -182,6 +184,8 @@ static int start_decode_buf_level = 0x8000; static unsigned int decode_timeout_val = 200; +static u32 run_ready_min_buf_num = 2; + /*data_resend_policy: bit 0, stream base resend data when decoding buf empty */ @@ -1301,11 +1305,13 @@ enum SliceType { /*USE_BUF_BLOCK*/ struct BUF_s { - unsigned long start_adr; - unsigned int size; - int used_flag; - unsigned int y_size; - ulong v4l_ref_buf_addr; + ulong start_adr; + u32 size; + u32 luma_size; + ulong header_addr; + u32 header_size; + int used_flag; + ulong v4l_ref_buf_addr; } /*BUF_t */; /* level 6, 6.1 maximum slice number is 800; other is 200 */ @@ -1396,6 +1402,8 @@ struct PIC_s { int max_mv; int min_mv; int avg_mv; + + bool vframe_bound; } /*PIC_t */; #define MAX_TILE_COL_NUM 10 @@ -1727,6 +1735,7 @@ struct hevc_state_s { bool is_used_v4l; void *v4l2_ctx; bool v4l_params_parsed; + u32 mem_map_mode; } /*hevc_stru_t */; #ifdef AGAIN_HAS_THRESHOLD @@ -2083,7 +2092,7 @@ static void restore_decode_state(struct hevc_state_s *hevc) static void hevc_init_stru(struct hevc_state_s *hevc, struct BuffInfo_s *buf_spec_i) { - //int i; + int i; INIT_LIST_HEAD(&hevc->log_list); hevc->work_space_buf = buf_spec_i; hevc->prefix_aux_size = 0; @@ -2140,10 +2149,14 @@ static void hevc_init_stru(struct hevc_state_s *hevc, else hevc->ignore_bufmgr_error = 0x0; - hevc->dec_result = DEC_RESULT_FREE_CANVAS; - vdec_schedule_work(&hevc->work); - /*for (i = 0; i < MAX_REF_PIC_NUM; i++) - hevc->m_PIC[i] = NULL;*/ + if (hevc->is_used_v4l) { + for (i = 0; i < MAX_REF_PIC_NUM; i++) { + if (hevc->m_PIC[i] != NULL) { + memset(hevc->m_PIC[i], 0 ,sizeof(struct PIC_s)); + hevc->m_PIC[i]->index = i; + } + } + } hevc->pic_num = 0; hevc->lcu_x_num_pre = 0; @@ -2575,6 +2588,32 @@ static void get_rpm_param(union param_u *params) } } +static int get_free_buf_idx(struct hevc_state_s *hevc) +{ + int index = INVALID_IDX; + struct PIC_s *pic; + int i; + + for (i = 0; i < MAX_REF_PIC_NUM; i++) { + pic = hevc->m_PIC[i]; + if (pic == NULL || + pic->index == -1 || + pic->BUF_index == -1) + continue; + + if (pic->output_mark == 0 && + pic->referenced == 0 && + pic->output_ready == 0 && + pic->cma_alloc_addr) { + pic->output_ready = 1; + index = i; + break; + } + } + + return index; +} + static struct PIC_s *get_pic_by_POC(struct hevc_state_s *hevc, int POC) { int i; @@ -2643,8 +2682,62 @@ static unsigned int log2i(unsigned int val) } static int init_buf_spec(struct hevc_state_s *hevc); + +static bool v4l_is_there_vframe_bound(struct hevc_state_s *hevc) +{ + int i; + + for (i = 0; i < MAX_REF_PIC_NUM; i++) { + struct PIC_s *pic = hevc->m_PIC[i]; + + if (pic && pic->vframe_bound) + return true; + } + + return false; +} + +static void v4l_mmu_buffer_release(struct hevc_state_s *hevc) +{ + int i; + + /* release workspace */ + if (hevc->bmmu_box) + decoder_bmmu_box_free_idx(hevc->bmmu_box, + BMMU_WORKSPACE_ID); + /* + * it's only when vframe get back to driver, right now we can be sure + * that vframe and fd are related. if the playback exits, the capture + * requires the upper app to release when the fd is closed, and others + * buffers drivers are released by driver. + */ + for (i = 0; i < MAX_REF_PIC_NUM; i++) { + struct PIC_s *pic = hevc->m_PIC[i]; + + if (pic && !pic->vframe_bound) { + if (hevc->bmmu_box) + decoder_bmmu_box_free_idx(hevc->bmmu_box, + VF_BUFFER_IDX(i)); + if (hevc->mmu_box) + decoder_mmu_box_free_idx(hevc->mmu_box, i); + + hevc_print(hevc, PRINT_FLAG_V4L_DETAIL, + "%s free buffer[%d], bmmu_box: %p, mmu_box: %p\n", + __func__, i, hevc->bmmu_box, hevc->mmu_box); + } + } +} + static void uninit_mmu_buffers(struct hevc_state_s *hevc) { + if (hevc->is_used_v4l && + v4l_is_there_vframe_bound(hevc)) { + if (get_double_write_mode(hevc) != 0x10) { + v4l_mmu_buffer_release(hevc); + return; + } + } + if (hevc->mmu_box) decoder_mmu_box_free(hevc->mmu_box); hevc->mmu_box = NULL; @@ -2733,7 +2826,6 @@ static void dealloc_mv_bufs(struct hevc_state_s *hevc) if (hevc->m_PIC[i] != NULL) hevc->m_PIC[i]->mv_buf_index = -1; } - } static int alloc_mv_buf(struct hevc_state_s *hevc, int i) @@ -2963,15 +3055,67 @@ static int cal_current_buf_size(struct hevc_state_s *hevc, return buf_size; } +static int v4l_alloc_buf(struct hevc_state_s *hevc, struct PIC_s *pic) +{ + int ret = -1; + int i = pic->index; + struct vdec_v4l2_buffer *fb = NULL; + + if (hevc->fatal_error & DECODER_FATAL_ERROR_NO_MEM) + return ret; + + ret = vdec_v4l_get_buffer(hevc->v4l2_ctx, &fb); + if (ret < 0) { + hevc_print(hevc, 0, "[%d] H265 get buffer fail.\n", + ((struct aml_vcodec_ctx *)(hevc->v4l2_ctx))->id); + return ret; + } + + if (hevc->mmu_enable) { + if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && + (IS_8K_SIZE(hevc->pic_w, hevc->pic_h))) + hevc->m_BUF[i].header_size = + ALIGN(MMU_COMPRESS_8K_HEADER_SIZE, 0x10000); + else + hevc->m_BUF[i].header_size = + ALIGN(MMU_COMPRESS_HEADER_SIZE, 0x10000); + + ret = decoder_bmmu_box_alloc_buf_phy(hevc->bmmu_box, + VF_BUFFER_IDX(i), hevc->m_BUF[i].header_size, + DRIVER_NAME, &hevc->m_BUF[i].header_addr); + if (ret < 0) { + hevc_print(hevc, PRINT_FLAG_ERROR, + "%s[%d], header size: %d, no mem fatal err\n", + __func__, i, hevc->m_BUF[i].header_size); + return ret; + } + } + + hevc->m_BUF[i].used_flag = 0; + hevc->m_BUF[i].v4l_ref_buf_addr = (ulong)fb; + pic->cma_alloc_addr = hevc->m_BUF[i].v4l_ref_buf_addr; + if (fb->num_planes == 1) { + hevc->m_BUF[i].start_adr = fb->m.mem[0].addr; + hevc->m_BUF[i].size = fb->m.mem[0].size; + hevc->m_BUF[i].luma_size = fb->m.mem[0].offset; + fb->m.mem[0].bytes_used = fb->m.mem[0].size; + } else if (fb->num_planes == 2) { + hevc->m_BUF[i].start_adr = fb->m.mem[0].addr; + hevc->m_BUF[i].size = fb->m.mem[0].size + fb->m.mem[1].size; + hevc->m_BUF[i].luma_size = fb->m.mem[0].size; + fb->m.mem[0].bytes_used = fb->m.mem[0].size; + fb->m.mem[1].bytes_used = fb->m.mem[1].size; + } + + return ret; +} + static int alloc_buf(struct hevc_state_s *hevc) { int i; int ret = -1; int buf_size = cal_current_buf_size(hevc, NULL); - if (hevc->is_used_v4l) - return 0; - if (hevc->fatal_error & DECODER_FATAL_ERROR_NO_MEM) return ret; @@ -2981,9 +3125,6 @@ static int alloc_buf(struct hevc_state_s *hevc) } if (i < BUF_POOL_SIZE) { if (buf_size > 0) { - /*get_cma_alloc_ref();*/ /*DEBUG_TMP*/ - /*alloc compress header first*/ - ret = decoder_bmmu_box_alloc_buf_phy (hevc->bmmu_box, VF_BUFFER_IDX(i), buf_size, @@ -3043,6 +3184,7 @@ static int alloc_buf(struct hevc_state_s *hevc) } else ret = 0; } + if (ret >= 0) { if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { hevc_print(hevc, 0, @@ -3088,7 +3230,6 @@ static void dealloc_unused_buf(struct hevc_state_s *hevc) hevc->m_BUF[i].size = 0; } } - } static void dealloc_pic_buf(struct hevc_state_s *hevc, @@ -3174,6 +3315,35 @@ static int get_alloc_pic_count(struct hevc_state_s *hevc) return alloc_pic_count; } +static int v4l_config_pic(struct hevc_state_s *hevc, struct PIC_s *pic) +{ + int i = pic->index; + int dw_mode = get_double_write_mode(hevc); + + if (hevc->mmu_enable) + pic->header_adr = hevc->m_BUF[i].header_addr; + + pic->BUF_index = i; + pic->POC = INVALID_POC; + pic->mc_canvas_y = pic->index; + pic->mc_canvas_u_v = pic->index; + + if (dw_mode & 0x10) { + pic->mc_y_adr = hevc->m_BUF[i].start_adr; + pic->mc_u_v_adr = pic->mc_y_adr + hevc->m_BUF[i].luma_size; + pic->mc_canvas_y = (pic->index << 1); + pic->mc_canvas_u_v = (pic->index << 1) + 1; + + pic->dw_y_adr = pic->mc_y_adr; + pic->dw_u_v_adr = pic->mc_u_v_adr; + } else if (dw_mode) { + pic->dw_y_adr = hevc->m_BUF[i].start_adr; + pic->dw_u_v_adr = pic->dw_y_adr + hevc->m_BUF[i].luma_size; + } + + return 0; +} + static int config_pic(struct hevc_state_s *hevc, struct PIC_s *pic) { int ret = -1; @@ -3189,45 +3359,8 @@ static int config_pic(struct hevc_state_s *hevc, struct PIC_s *pic) struct buf_stru_s buf_stru; int buf_size = cal_current_buf_size(hevc, &buf_stru); int dw_mode = get_double_write_mode(hevc); - struct vdec_v4l2_buffer *fb = NULL; - - if (hevc->is_used_v4l) - buf_size = 0; for (i = 0; i < BUF_POOL_SIZE; i++) { - if (hevc->is_used_v4l && !hevc->m_BUF[i].start_adr) { - ret = vdec_v4l_get_buffer(hevc->v4l2_ctx, &fb); - if (ret) { - hevc_print(hevc, PRINT_FLAG_V4L_DETAIL, - "[%d] get fb fail.\n", - ((struct aml_vcodec_ctx *) - (hevc->v4l2_ctx))->id); - return ret; - } - - hevc->m_BUF[i].used_flag = 0; - hevc->m_BUF[i].v4l_ref_buf_addr = (ulong)fb; - if (fb->num_planes == 1) { - hevc->m_BUF[i].start_adr = fb->m.mem[0].addr; - hevc->m_BUF[i].size = fb->m.mem[0].size; - hevc->m_BUF[i].y_size = fb->m.mem[0].offset; - fb->m.mem[0].bytes_used = fb->m.mem[0].size; - } else if (fb->num_planes == 2) { - hevc->m_BUF[i].start_adr = fb->m.mem[0].addr; - hevc->m_BUF[i].size = fb->m.mem[0].size + fb->m.mem[1].size; - hevc->m_BUF[i].y_size = fb->m.mem[0].size; - fb->m.mem[0].bytes_used = fb->m.mem[0].size; - fb->m.mem[1].bytes_used = fb->m.mem[1].size; - } - - pic->BUF_index = i; - - hevc_print(hevc, PRINT_FLAG_V4L_DETAIL, - "[%d] %s(), v4l ref buf addr: 0x%x\n", - ((struct aml_vcodec_ctx *) - (hevc->v4l2_ctx))->id, __func__, fb); - } - if (hevc->m_BUF[i].start_adr != 0 && hevc->m_BUF[i].used_flag == 0 && buf_size <= hevc->m_BUF[i].size) { @@ -3251,8 +3384,7 @@ static int config_pic(struct hevc_state_s *hevc, struct PIC_s *pic) } else y_adr = hevc->m_BUF[i].start_adr; - if (!hevc->is_used_v4l) - y_adr = ((y_adr + 0xffff) >> 16) << 16; /*64k alignment*/ + y_adr = ((y_adr + 0xffff) >> 16) << 16; /*64k alignment*/ pic->POC = INVALID_POC; /*ensure get_pic_by_POC() @@ -3268,15 +3400,9 @@ static int config_pic(struct hevc_state_s *hevc, struct PIC_s *pic) pic->mc_canvas_y = pic->index; pic->mc_canvas_u_v = pic->index; if (dw_mode & 0x10) { - if (hevc->is_used_v4l) { - pic->mc_y_adr = y_adr; - pic->mc_u_v_adr = y_adr + hevc->m_BUF[i].y_size; - } else { - pic->mc_y_adr = y_adr; - pic->mc_u_v_adr = y_adr + - ((buf_stru.mc_buffer_size_u_v_h << 16) << 1); - } - + pic->mc_y_adr = y_adr; + pic->mc_u_v_adr = y_adr + + ((buf_stru.mc_buffer_size_u_v_h << 16) << 1); pic->mc_canvas_y = (pic->index << 1); pic->mc_canvas_u_v = (pic->index << 1) + 1; @@ -3285,10 +3411,9 @@ static int config_pic(struct hevc_state_s *hevc, struct PIC_s *pic) } else if (dw_mode) { pic->dw_y_adr = y_adr; pic->dw_u_v_adr = pic->dw_y_adr + - ((buf_stru.mc_buffer_size_u_v_h << 16) << 1); + ((buf_stru.mc_buffer_size_u_v_h << 16) << 1); } - if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { hevc_print(hevc, 0, "%s index %d BUF_index %d mc_y_adr %x\n", @@ -3299,8 +3424,6 @@ static int config_pic(struct hevc_state_s *hevc, struct PIC_s *pic) hevc_print(hevc, 0, "mmu double write adr %ld\n", pic->cma_alloc_addr); - - } ret = 0; @@ -3313,30 +3436,36 @@ static void init_pic_list(struct hevc_state_s *hevc) int init_buf_num = get_work_pic_num(hevc); int dw_mode = get_double_write_mode(hevc); struct vdec_s *vdec = hw_to_vdec(hevc); - /*alloc decoder buf*/ - for (i = 0; i < init_buf_num; i++) { - if (alloc_buf(hevc) < 0) { - if (i <= 8) { - /*if alloced (i+1)>=9 - don't send errors.*/ - hevc->fatal_error |= - DECODER_FATAL_ERROR_NO_MEM; + /*alloc decoder buf will be delay if work on v4l. */ + if (!hevc->is_used_v4l) { + for (i = 0; i < init_buf_num; i++) { + if (alloc_buf(hevc) < 0) { + if (i <= 8) { + /*if alloced (i+1)>=9 + don't send errors.*/ + hevc->fatal_error |= + DECODER_FATAL_ERROR_NO_MEM; + } + break; } - break; } } for (i = 0; i < init_buf_num; i++) { - struct PIC_s *pic = - vmalloc(sizeof(struct PIC_s)); - if (pic == NULL) { - hevc_print(hevc, 0, - "%s: alloc pic %d fail!!!\n", - __func__, i); - break; + struct PIC_s *pic = hevc->m_PIC[i]; + + if (!pic) { + pic = vmalloc(sizeof(struct PIC_s)); + if (pic == NULL) { + hevc_print(hevc, 0, + "%s: alloc pic %d fail!!!\n", + __func__, i); + break; + } + hevc->m_PIC[i] = pic; } memset(pic, 0, sizeof(struct PIC_s)); - hevc->m_PIC[i] = pic; + pic->index = i; pic->BUF_index = -1; pic->mv_buf_index = -1; @@ -3349,6 +3478,7 @@ static void init_pic_list(struct hevc_state_s *hevc) pic->height = hevc->pic_h; pic->double_write_mode = dw_mode; + /*config canvas will be delay if work on v4l. */ if (!hevc->is_used_v4l) { if (config_pic(hevc, pic) < 0) { if (get_dbg_flag(hevc)) @@ -3365,16 +3495,20 @@ static void init_pic_list(struct hevc_state_s *hevc) } for (; i < MAX_REF_PIC_NUM; i++) { - struct PIC_s *pic = - vmalloc(sizeof(struct PIC_s)); - if (pic == NULL) { - hevc_print(hevc, 0, - "%s: alloc pic %d fail!!!\n", - __func__, i); - break; + struct PIC_s *pic = hevc->m_PIC[i]; + + if (!pic) { + pic = vmalloc(sizeof(struct PIC_s)); + if (pic == NULL) { + hevc_print(hevc, 0, + "%s: alloc pic %d fail!!!\n", + __func__, i); + break; + } + hevc->m_PIC[i] = pic; } memset(pic, 0, sizeof(struct PIC_s)); - hevc->m_PIC[i] = pic; + pic->index = -1; pic->BUF_index = -1; if (vdec->parallel_dec == 1) { @@ -5121,7 +5255,7 @@ static void config_sao_hw(struct hevc_state_s *hevc, union param_u *params) #if 0 data32 = READ_VREG(HEVC_SAO_CTRL1); data32 &= (~0x3000); - data32 |= (mem_map_mode << + data32 |= (hevc->mem_map_mode << 12); /* [13:12] axi_aformat, @@ -5131,7 +5265,7 @@ static void config_sao_hw(struct hevc_state_s *hevc, union param_u *params) data32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG); data32 &= (~0x30); - data32 |= (mem_map_mode << + data32 |= (hevc->mem_map_mode << 4); /* [5:4] -- address_format @@ -5142,7 +5276,7 @@ static void config_sao_hw(struct hevc_state_s *hevc, union param_u *params) /* m8baby test1902 */ data32 = READ_VREG(HEVC_SAO_CTRL1); data32 &= (~0x3000); - data32 |= (mem_map_mode << + data32 |= (hevc->mem_map_mode << 12); /* [13:12] axi_aformat, 0-Linear, @@ -5213,7 +5347,7 @@ static void config_sao_hw(struct hevc_state_s *hevc, union param_u *params) data32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG); data32 &= (~0x30); /* [5:4] -- address_format 00:linear 01:32x32 10:64x32 */ - data32 |= (mem_map_mode << + data32 |= (hevc->mem_map_mode << 4); data32 &= (~0xF); data32 |= 0xf; /* valid only when double write only */ @@ -5420,6 +5554,7 @@ static struct PIC_s *get_new_pic(struct hevc_state_s *hevc, && pic->output_ready == 0 && pic->width == hevc->pic_w && pic->height == hevc->pic_h + && pic->vf_ref == 0 ) { if (new_pic) { if (new_pic->POC != INVALID_POC) { @@ -5532,6 +5667,124 @@ static struct PIC_s *get_new_pic(struct hevc_state_s *hevc, return new_pic; } +static struct PIC_s *v4l_get_new_pic(struct hevc_state_s *hevc, + union param_u *rpm_param) +{ + int ret; + struct aml_vcodec_ctx * v4l = hevc->v4l2_ctx; + struct v4l_buff_pool *pool = &v4l->cap_pool; + struct PIC_s *new_pic = NULL; + struct PIC_s *pic = NULL; + int i; + + for (i = 0; i < pool->in; ++i) { + u32 state = (pool->seq[i] >> 16); + u32 index = (pool->seq[i] & 0xffff); + + switch (state) { + case V4L_CAP_BUFF_IN_DEC: + pic = hevc->m_PIC[i]; + if (pic && (pic->index != -1) && + (pic->output_mark == 0) && + (pic->referenced == 0) && + (pic->output_ready == 0) && + (pic->width == hevc->pic_w) && + (pic->height == hevc->pic_h) && + (pic->vf_ref == 0) && + pic->cma_alloc_addr) { + new_pic = pic; + } + break; + case V4L_CAP_BUFF_IN_M2M: + pic = hevc->m_PIC[index]; + pic->width = hevc->pic_w; + pic->height = hevc->pic_h; + if ((pic->index != -1) && + !v4l_alloc_buf(hevc, pic)) { + v4l_config_pic(hevc, pic); + init_pic_list_hw(hevc); + new_pic = pic; + } + break; + default: + pr_err("v4l buffer state err %d.\n", state); + break; + } + + if (new_pic) + break; + } + + if (new_pic == NULL) + return NULL; + + new_pic->double_write_mode = get_double_write_mode(hevc); + if (new_pic->double_write_mode) + set_canvas(hevc, new_pic); + + if (get_mv_buf(hevc, new_pic) < 0) + return NULL; + + if (hevc->mmu_enable) { + ret = H265_alloc_mmu(hevc, new_pic, + rpm_param->p.bit_depth, + hevc->frame_mmu_map_addr); + if (ret != 0) { + put_mv_buf(hevc, new_pic); + hevc_print(hevc, 0, + "can't alloc need mmu1,idx %d ret =%d\n", + new_pic->decode_idx, ret); + return NULL; + } + } + + new_pic->referenced = 1; + new_pic->decode_idx = hevc->decode_idx; + new_pic->slice_idx = 0; + new_pic->referenced = 1; + new_pic->output_mark = 0; + new_pic->recon_mark = 0; + new_pic->error_mark = 0; + new_pic->dis_mark = 0; + /* new_pic->output_ready = 0; */ + new_pic->num_reorder_pic = rpm_param->p.sps_num_reorder_pics_0; + new_pic->losless_comp_body_size = hevc->losless_comp_body_size; + new_pic->POC = hevc->curr_POC; + new_pic->pic_struct = hevc->curr_pic_struct; + + if (new_pic->aux_data_buf) + release_aux_data(hevc, new_pic); + new_pic->mem_saving_mode = + hevc->mem_saving_mode; + new_pic->bit_depth_luma = + hevc->bit_depth_luma; + new_pic->bit_depth_chroma = + hevc->bit_depth_chroma; + new_pic->video_signal_type = + hevc->video_signal_type; + + new_pic->conformance_window_flag = + hevc->param.p.conformance_window_flag; + new_pic->conf_win_left_offset = + hevc->param.p.conf_win_left_offset; + new_pic->conf_win_right_offset = + hevc->param.p.conf_win_right_offset; + new_pic->conf_win_top_offset = + hevc->param.p.conf_win_top_offset; + new_pic->conf_win_bottom_offset = + hevc->param.p.conf_win_bottom_offset; + new_pic->chroma_format_idc = + hevc->param.p.chroma_format_idc; + + hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, + "%s: index %d, buf_idx %d, decode_idx %d, POC %d\n", + __func__, new_pic->index, + new_pic->BUF_index, new_pic->decode_idx, + new_pic->POC); + + return new_pic; +} + static int get_display_pic_num(struct hevc_state_s *hevc) { int i; @@ -6768,7 +7021,9 @@ static int hevc_slice_segment_header_process(struct hevc_state_s *hevc, set_aux_data(hevc, hevc->cur_pic, 1, 0); #endif /* new pic */ - hevc->cur_pic = get_new_pic(hevc, rpm_param); + hevc->cur_pic = hevc->is_used_v4l ? + v4l_get_new_pic(hevc, rpm_param) : + get_new_pic(hevc, rpm_param); if (hevc->cur_pic == NULL) { if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) dump_pic_list(hevc); @@ -6829,7 +7084,9 @@ static int hevc_slice_segment_header_process(struct hevc_state_s *hevc, } else { if (hevc->wait_buf == 1) { pic_list_process(hevc); - hevc->cur_pic = get_new_pic(hevc, rpm_param); + hevc->cur_pic = hevc->is_used_v4l ? + v4l_get_new_pic(hevc, rpm_param) : + get_new_pic(hevc, rpm_param); if (hevc->cur_pic == NULL) return -1; @@ -7127,17 +7384,17 @@ static int H265_alloc_mmu(struct hevc_state_s *hevc, struct PIC_s *new_pic, return -1; } ret = decoder_mmu_box_alloc_idx( - hevc->mmu_box, - cur_buf_idx, - cur_mmu_4k_number, - mmu_index_adr); + hevc->mmu_box, + cur_buf_idx, + cur_mmu_4k_number, + mmu_index_adr); if (ret == 0) new_pic->scatter_alloc = 1; + hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, - "%s pic index %d page count(%d) ret =%d\n", - __func__, cur_buf_idx, - cur_mmu_4k_number, - ret); + "%s pic index %d page count(%d) ret =%d\n", + __func__, cur_buf_idx, + cur_mmu_4k_number, ret); return ret; } @@ -7327,7 +7584,7 @@ static void set_canvas(struct hevc_state_s *hevc, struct PIC_s *pic) struct vdec_s *vdec = hw_to_vdec(hevc); int canvas_w = ALIGN(pic->width, 64)/4; int canvas_h = ALIGN(pic->height, 32)/4; - int blkmode = mem_map_mode; + int blkmode = hevc->mem_map_mode; /*CANVAS_BLKMODE_64X32*/ #ifdef SUPPORT_10BIT @@ -7337,7 +7594,7 @@ static void set_canvas(struct hevc_state_s *hevc, struct PIC_s *pic) canvas_h = pic->height / get_double_write_ratio(hevc, pic->double_write_mode); - if (mem_map_mode == 0) + if (hevc->mem_map_mode == 0) canvas_w = ALIGN(canvas_w, 32); else canvas_w = ALIGN(canvas_w, 64); @@ -7355,10 +7612,10 @@ static void set_canvas(struct hevc_state_s *hevc, struct PIC_s *pic) canvas_config_ex(pic->y_canvas_index, pic->dw_y_adr, canvas_w, canvas_h, - CANVAS_ADDR_NOWRAP, blkmode, 0x7); + CANVAS_ADDR_NOWRAP, blkmode, hevc->is_used_v4l ? 0 : 7); canvas_config_ex(pic->uv_canvas_index, pic->dw_u_v_adr, canvas_w, canvas_h, - CANVAS_ADDR_NOWRAP, blkmode, 0x7); + CANVAS_ADDR_NOWRAP, blkmode, hevc->is_used_v4l ? 0 : 7); #ifdef MULTI_INSTANCE_SUPPORT pic->canvas_config[0].phy_addr = pic->dw_y_adr; @@ -7368,7 +7625,7 @@ static void set_canvas(struct hevc_state_s *hevc, struct PIC_s *pic) canvas_h; pic->canvas_config[0].block_mode = blkmode; - pic->canvas_config[0].endian = 7; + pic->canvas_config[0].endian = hevc->is_used_v4l ? 0 : 7; pic->canvas_config[1].phy_addr = pic->dw_u_v_adr; @@ -7378,7 +7635,7 @@ static void set_canvas(struct hevc_state_s *hevc, struct PIC_s *pic) canvas_h; pic->canvas_config[1].block_mode = blkmode; - pic->canvas_config[1].endian = 7; + pic->canvas_config[1].endian = hevc->is_used_v4l ? 0 : 7; #endif } else { if (!hevc->mmu_enable) { @@ -7394,10 +7651,10 @@ static void set_canvas(struct hevc_state_s *hevc, struct PIC_s *pic) canvas_config_ex(pic->y_canvas_index, pic->mc_y_adr, canvas_w, canvas_h, - CANVAS_ADDR_NOWRAP, blkmode, 0x7); + CANVAS_ADDR_NOWRAP, blkmode, hevc->is_used_v4l ? 0 : 7); canvas_config_ex(pic->uv_canvas_index, pic->mc_u_v_adr, canvas_w, canvas_h, - CANVAS_ADDR_NOWRAP, blkmode, 0x7); + CANVAS_ADDR_NOWRAP, blkmode, hevc->is_used_v4l ? 0 : 7); } } #else @@ -7413,10 +7670,10 @@ static void set_canvas(struct hevc_state_s *hevc, struct PIC_s *pic) canvas_config_ex(pic->y_canvas_index, pic->mc_y_adr, canvas_w, canvas_h, - CANVAS_ADDR_NOWRAP, blkmode, 0x7); + CANVAS_ADDR_NOWRAP, blkmode, hevc->is_used_v4l ? 0 : 7); canvas_config_ex(pic->uv_canvas_index, pic->mc_u_v_adr, canvas_w, canvas_h, - CANVAS_ADDR_NOWRAP, blkmode, 0x7); + CANVAS_ADDR_NOWRAP, blkmode, hevc->is_used_v4l ? 0 : 7); #endif } @@ -7732,6 +7989,20 @@ static void set_frame_info(struct hevc_state_s *hevc, struct vframe_s *vf, vf_dp->content_light_level.present_flag = 1; } else vf_dp->content_light_level.present_flag = 0; + + if (hevc->is_used_v4l && + ((hevc->sei_present_flag & SEI_HDR10PLUS_MASK) || + (vf_dp->present_flag) || + (vf_dp->content_light_level.present_flag))) { + struct aml_vdec_hdr_infos hdr; + struct aml_vcodec_ctx *ctx = + (struct aml_vcodec_ctx *)(hevc->v4l2_ctx); + + memset(&hdr, 0, sizeof(hdr)); + hdr.signal_type = vf->signal_type; + hdr.color_parms = *vf_dp; + vdec_v4l_set_hdr_infos(ctx, &hdr); + } } static int vh265_vf_states(struct vframe_states *states, void *op_arg) @@ -7907,6 +8178,7 @@ static struct vframe_s *vh265_vf_get(void *op_arg) } #endif hevc->show_frame_num++; + vf->index_disp = hevc->vf_get_count; hevc->vf_get_count++; if (kfifo_peek(&hevc->display_q, &next_vf)) { @@ -7962,6 +8234,8 @@ static void vh265_vf_put(struct vframe_s *vf, void *op_arg) if (index_top != 0xff && index_top < MAX_REF_PIC_NUM && hevc->m_PIC[index_top]) { + if (hevc->is_used_v4l) + hevc->m_PIC[index_top]->vframe_bound = true; if (hevc->m_PIC[index_top]->vf_ref > 0) { hevc->m_PIC[index_top]->vf_ref--; @@ -7978,6 +8252,8 @@ static void vh265_vf_put(struct vframe_s *vf, void *op_arg) if (index_bot != 0xff && index_bot < MAX_REF_PIC_NUM && hevc->m_PIC[index_bot]) { + if (hevc->is_used_v4l) + hevc->m_PIC[index_bot]->vframe_bound = true; if (hevc->m_PIC[index_bot]->vf_ref > 0) { hevc->m_PIC[index_bot]->vf_ref--; @@ -8021,6 +8297,10 @@ static int vh265_event_cb(int type, void *data, void *op_arg) (struct provider_aux_req_s *)data; unsigned char index; + if (!req->vf) { + req->aux_size = hevc->vf_put_count; + return 0; + } spin_lock_irqsave(&lock, flags); index = req->vf->index & 0xff; req->aux_buf = NULL; @@ -8310,16 +8590,11 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic) vf->v4l_mem_handle = hevc->m_BUF[pic->BUF_index].v4l_ref_buf_addr; if (hevc->mmu_enable) { - if (vdec_v4l_binding_fd_and_vf(vf->v4l_mem_handle, vf) < 0) { - hevc_print(hevc, PRINT_FLAG_V4L_DETAIL, - "v4l: binding vf fail.\n"); - return -1; - } + vf->mm_box.bmmu_box = hevc->bmmu_box; + vf->mm_box.bmmu_idx = VF_BUFFER_IDX(pic->BUF_index); + vf->mm_box.mmu_box = hevc->mmu_box; + vf->mm_box.mmu_idx = pic->index; } - hevc_print(hevc, PRINT_FLAG_V4L_DETAIL, - "[%d] %s(), v4l mem handle: 0x%lx\n", - ((struct aml_vcodec_ctx *)(hevc->v4l2_ctx))->id, - __func__, vf->v4l_mem_handle); } #ifdef MULTI_INSTANCE_SUPPORT @@ -8454,6 +8729,7 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic) if (pic->double_write_mode) { vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; vf->type |= VIDTYPE_VIU_NV21; + if ((pic->double_write_mode == 3) && (!(IS_8K_SIZE(pic->width, pic->height)))) { vf->type |= VIDTYPE_COMPRESS; @@ -8840,27 +9116,31 @@ static int notify_v4l_eos(struct vdec_s *vdec) { struct hevc_state_s *hw = (struct hevc_state_s *)vdec->private; struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)(hw->v4l2_ctx); - struct vframe_s *vf = NULL; + struct vframe_s *vf = &hw->vframe_dummy; struct vdec_v4l2_buffer *fb = NULL; + int index = INVALID_IDX; + ulong expires; if (hw->is_used_v4l && hw->eos) { - if (kfifo_get(&hw->newframe_q, &vf) == 0 || vf == NULL) { - hevc_print(hw, 0, - "%s fatal error, no available buffer slot.\n", - __func__); - return -1; + expires = jiffies + msecs_to_jiffies(2000); + while (INVALID_IDX == (index = get_free_buf_idx(hw))) { + if (time_after(jiffies, expires) || + v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx)) + break; } - if (vdec_v4l_get_buffer(hw->v4l2_ctx, &fb)) { - pr_err("[%d] get fb fail.\n", ctx->id); - return -1; + if (index == INVALID_IDX) { + if (vdec_v4l_get_buffer(hw->v4l2_ctx, &fb) < 0) { + pr_err("[%d] EOS get free buff fail.\n", ctx->id); + return -1; + } } - vf->type |= VIDTYPE_V4L_EOS; - vf->timestamp = ULONG_MAX; - vf->v4l_mem_handle = (unsigned long)fb; - vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L; - + vf->type |= VIDTYPE_V4L_EOS; + vf->timestamp = ULONG_MAX; + vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L; + vf->v4l_mem_handle = (index == INVALID_IDX) ? (ulong)fb : + hw->m_BUF[index].v4l_ref_buf_addr; kfifo_put(&hw->display_q, (const struct vframe_s *)vf); vf_notify_receiver(vdec->vf_provider_name, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); @@ -9481,7 +9761,8 @@ pic_done: check_pic_decoded_error(hevc, READ_VREG(HEVC_PARSER_LCU_START) & 0xffffff); if (hevc->cur_pic != NULL && - (READ_VREG(HEVC_PARSER_LCU_START) & 0xffffff) == 0) + (READ_VREG(HEVC_PARSER_LCU_START) & 0xffffff) == 0 + && (hevc->lcu_x_num * hevc->lcu_y_num != 1)) hevc->cur_pic->error_mark = 1; force_output: pic_display = output_pic(hevc, 1); @@ -9877,18 +10158,18 @@ force_output: (struct aml_vcodec_ctx *)(hevc->v4l2_ctx); if (ctx->param_sets_from_ucode && !hevc->v4l_params_parsed) { - struct aml_vdec_pic_infos info; + struct aml_vdec_ps_infos ps; hevc->frame_width = hevc->param.p.pic_width_in_luma_samples; hevc->frame_height = hevc->param.p.pic_height_in_luma_samples; - info.visible_width = hevc->frame_width; - info.visible_height = hevc->frame_height; - info.coded_width = ALIGN(hevc->frame_width, 32); - info.coded_height = ALIGN(hevc->frame_height, 32); - info.dpb_size = get_work_pic_num(hevc); + ps.visible_width = hevc->frame_width; + ps.visible_height = hevc->frame_height; + ps.coded_width = ALIGN(hevc->frame_width, 32); + ps.coded_height = ALIGN(hevc->frame_height, 32); + ps.dpb_size = get_work_pic_num(hevc); hevc->v4l_params_parsed = true; /*notice the v4l2 codec.*/ - vdec_v4l_set_pic_infos(ctx, &info); + vdec_v4l_set_ps_infos(ctx, &ps); } } @@ -11274,7 +11555,7 @@ static unsigned char is_new_pic_available(struct hevc_state_s *hevc) /*decode. all reference frames are removed and setting error flag.*/ /*3 represents 2 filed are needed for back-end display and 1 filed is needed for decoding*/ /*when file is interlace.*/ - if ((new_pic == NULL) && + if ((!hevc->is_used_v4l) && (new_pic == NULL) && (ref_pic >= get_work_pic_num(hevc) - hevc->sps_num_reorder_pics_0 - 3)) { @@ -11334,6 +11615,14 @@ static int vmh265_stop(struct hevc_state_s *hevc) hevc_local_uninit(hevc); + hevc->init_flag = 0; + hevc->first_sc_checked = 0; + cancel_work_sync(&hevc->notify_work); + cancel_work_sync(&hevc->set_clk_work); + cancel_work_sync(&hevc->timeout_work); + + uninit_mmu_buffers(hevc); + if (use_cma) { hevc->uninit_list = 1; reset_process_time(hevc); @@ -11349,13 +11638,7 @@ static int vmh265_stop(struct hevc_state_s *hevc) msleep(20); #endif } - hevc->init_flag = 0; - hevc->first_sc_checked = 0; - cancel_work_sync(&hevc->notify_work); - cancel_work_sync(&hevc->set_clk_work); cancel_work_sync(&hevc->work); - cancel_work_sync(&hevc->timeout_work); - uninit_mmu_buffers(hevc); vfree(hevc->fw); hevc->fw = NULL; @@ -11971,11 +12254,15 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) if (ctx->param_sets_from_ucode && !ctx->v4l_codec_ready && - hevc->v4l_params_parsed) + hevc->v4l_params_parsed) { ret = 0; /*the params has parsed.*/ + } else if (!ctx->v4l_codec_dpb_ready) { + if (v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) < + run_ready_min_buf_num) + ret = 0; + } } - if (ret) not_run_ready[hevc->index] = 0; else @@ -12162,9 +12449,26 @@ static void run(struct vdec_s *vdec, unsigned long mask, hevc->stat |= STAT_VDEC_RUN; } -static void reset(struct vdec_s *vdec) +static void aml_free_canvas(struct vdec_s *vdec) { + int i; + struct hevc_state_s *hevc = + (struct hevc_state_s *)vdec->private; + + for (i = 0; i < MAX_REF_PIC_NUM; i++) { + struct PIC_s *pic = hevc->m_PIC[i]; + + if (pic) { + if (vdec->parallel_dec == 1) { + vdec->free_canvas_ex(pic->y_canvas_index, vdec->id); + vdec->free_canvas_ex(pic->uv_canvas_index, vdec->id); + } + } + } +} +static void reset(struct vdec_s *vdec) +{ struct hevc_state_s *hevc = (struct hevc_state_s *)vdec->private; int i; @@ -12185,6 +12489,7 @@ static void reset(struct vdec_s *vdec) hevc->init_flag = 0; hevc->pic_list_init_flag = 0; dealloc_mv_bufs(hevc); + aml_free_canvas(vdec); hevc_local_uninit(hevc); if (vh265_local_init(hevc) < 0) pr_debug(" %s local init fail\n", __func__); @@ -12687,6 +12992,20 @@ static int ammvdec_h265_probe(struct platform_device *pdev) hevc->max_pic_h = config_val; } + if (get_config_int(pdata->config, + "parm_v4l_codec_enable", + &config_val) == 0) + hevc->is_used_v4l = config_val; + + if (get_config_int(pdata->config, + "parm_v4l_buffer_margin", + &config_val) == 0) + hevc->dynamic_buf_num_margin = config_val; + + if (get_config_int(pdata->config, + "parm_v4l_canvas_mem_mode", + &config_val) == 0) + hevc->mem_map_mode = config_val; #endif } else { if (pdata->sys_info) @@ -12698,10 +13017,14 @@ static int ammvdec_h265_probe(struct platform_device *pdev) } hevc->double_write_mode = double_write_mode; } - if (hevc->save_buffer_mode && dynamic_buf_num_margin > 2) - hevc->dynamic_buf_num_margin = dynamic_buf_num_margin -2; - else - hevc->dynamic_buf_num_margin = dynamic_buf_num_margin; + if (!hevc->is_used_v4l) { + if (hevc->save_buffer_mode && dynamic_buf_num_margin > 2) + hevc->dynamic_buf_num_margin = dynamic_buf_num_margin -2; + else + hevc->dynamic_buf_num_margin = dynamic_buf_num_margin; + + hevc->mem_map_mode = mem_map_mode; + } if (mmu_enable_force == 0) { if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_GXL) @@ -12710,19 +13033,6 @@ static int ammvdec_h265_probe(struct platform_device *pdev) hevc->mmu_enable = 1; } - hevc->is_used_v4l = (((unsigned long) - hevc->vh265_amstream_dec_info.param & 0x80) >> 7); - if (hevc->is_used_v4l) { - hevc->mmu_enable = (((unsigned long) // scatter mem - hevc->vh265_amstream_dec_info.param & 0x100) >> 8); - if (!hevc->mmu_enable) - hevc->double_write_mode = 0x10; - - hevc_print(hevc, PRINT_FLAG_V4L_DETAIL, - "%s v4: enable mmu %d.\n", - __func__, hevc->mmu_enable); - } - if (init_mmu_buffers(hevc) < 0) { hevc_print(hevc, 0, "\n 265 mmu init failed!\n"); diff --git a/drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c b/drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c index c8c3eaa..493231b 100644 --- a/drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c +++ b/drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c @@ -44,6 +44,7 @@ #include <linux/amlogic/media/codec_mm/configs.h> #include "../utils/firmware.h" #include "../utils/vdec_v4l2_buffer_ops.h" +#include "../utils/config_parser.h" #define MEM_NAME "codec_mmjpeg" @@ -72,8 +73,9 @@ #define PICINFO_INTERLACE_AVI1_BOT 0x0010 #define PICINFO_INTERLACE_FIRST 0x0010 -#define VF_POOL_SIZE 16 -#define DECODE_BUFFER_NUM_MAX 4 +#define VF_POOL_SIZE 64 +#define DECODE_BUFFER_NUM_MAX 16 +#define DECODE_BUFFER_NUM_DEF 4 #define MAX_BMMU_BUFFER_NUM DECODE_BUFFER_NUM_MAX #define DEFAULT_MEM_SIZE (32*SZ_1M) @@ -94,7 +96,9 @@ static int vmjpeg_vf_states(struct vframe_states *states, void *); static int vmjpeg_event_cb(int type, void *data, void *private_data); static void vmjpeg_work(struct work_struct *work); static int pre_decode_buf_level = 0x800; +static int start_decode_buf_level = 0x2000; static u32 without_display_mode; +static u32 dynamic_buf_num_margin; #undef pr_info #define pr_info printk unsigned int mmjpeg_debug_mask = 0xff; @@ -111,6 +115,7 @@ unsigned int mmjpeg_debug_mask = 0xff; #define PRINT_FRAMEBASE_DATA 0x0400 #define PRINT_FLAG_TIMEOUT_STATUS 0x1000 #define PRINT_FLAG_V4L_DETAIL 0x8000 +#define IGNORE_PARAM_FROM_CONFIG 0x8000000 int mmjpeg_debug_print(int index, int debug_flag, const char *fmt, ...) { @@ -215,6 +220,8 @@ struct vdec_mjpeg_hw_s { bool is_used_v4l; void *v4l2_ctx; bool v4l_params_parsed; + int buf_num; + int dynamic_buf_num_margin; }; static void reset_process_time(struct vdec_mjpeg_hw_s *hw); @@ -275,7 +282,7 @@ static irqreturn_t vmjpeg_isr(struct vdec_s *vdec, int irq) reg = READ_VREG(MREG_FROM_AMRISC); index = READ_VREG(AV_SCRATCH_5); - if (index >= DECODE_BUFFER_NUM_MAX) { + if (index >= hw->buf_num) { pr_err("fatal error, invalid buffer index."); return IRQ_HANDLED; } @@ -291,15 +298,15 @@ static irqreturn_t vmjpeg_isr(struct vdec_s *vdec, int irq) (struct aml_vcodec_ctx *)(hw->v4l2_ctx); if (ctx->param_sets_from_ucode && !hw->v4l_params_parsed) { - struct aml_vdec_pic_infos info; + struct aml_vdec_ps_infos ps; - info.visible_width = hw->frame_width; - info.visible_height = hw->frame_height; - info.coded_width = ALIGN(hw->frame_width, 64); - info.coded_height = ALIGN(hw->frame_height, 64); - info.dpb_size = MAX_BMMU_BUFFER_NUM - 1; + ps.visible_width = hw->frame_width; + ps.visible_height = hw->frame_height; + ps.coded_width = ALIGN(hw->frame_width, 64); + ps.coded_height = ALIGN(hw->frame_height, 64); + ps.dpb_size = hw->buf_num; hw->v4l_params_parsed = true; - vdec_v4l_set_pic_infos(ctx, &info); + vdec_v4l_set_ps_infos(ctx, &ps); } if (!ctx->v4l_codec_ready) @@ -309,11 +316,6 @@ static irqreturn_t vmjpeg_isr(struct vdec_s *vdec, int irq) if (hw->is_used_v4l) { vf->v4l_mem_handle = hw->buffer_spec[index].v4l_ref_buf_addr; - if (vdec_v4l_binding_fd_and_vf(vf->v4l_mem_handle, vf) < 0) { - mmjpeg_debug_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, - "v4l: binding vf fail.\n"); - return -1; - } mmjpeg_debug_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, "[%d] %s(), v4l mem handle: 0x%lx\n", ((struct aml_vcodec_ctx *)(hw->v4l2_ctx))->id, @@ -469,7 +471,7 @@ static void vmjpeg_canvas_init(struct vdec_mjpeg_hw_s *hw) decbuf_uv_size = 0x80000; decbuf_size = 0x300000; - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + for (i = 0; i < hw->buf_num; i++) { int canvas; if (hw->is_used_v4l) { @@ -645,9 +647,10 @@ static void vmjpeg_dump_state(struct vdec_s *vdec) mmjpeg_debug_print(DECODE_ID(hw), 0, "====== %s\n", __func__); mmjpeg_debug_print(DECODE_ID(hw), 0, - "width/height (%d/%d)\n", + "width/height (%d/%d) buf_num %d\n", hw->frame_width, - hw->frame_height + hw->frame_height, + hw->buf_num ); mmjpeg_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", @@ -839,7 +842,7 @@ static int vmjpeg_v4l_alloc_buff_config_canvas(struct vdec_mjpeg_hw_s *hw, int i return 0; ret = vdec_v4l_get_buffer(hw->v4l2_ctx, &fb); - if (ret) { + if (ret < 0) { mmjpeg_debug_print(DECODE_ID(hw), 0, "[%d] get fb fail.\n", ((struct aml_vcodec_ctx *) @@ -941,28 +944,40 @@ static int vmjpeg_v4l_alloc_buff_config_canvas(struct vdec_mjpeg_hw_s *hw, int i return 0; } +static int vmjpeg_get_buf_num(struct vdec_mjpeg_hw_s *hw) +{ + int buf_num = DECODE_BUFFER_NUM_DEF; + + buf_num += hw->dynamic_buf_num_margin; + + if (buf_num > DECODE_BUFFER_NUM_MAX) + buf_num = DECODE_BUFFER_NUM_MAX; + + return buf_num; +} + static bool is_enough_free_buffer(struct vdec_mjpeg_hw_s *hw) { int i; - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + for (i = 0; i < hw->buf_num; i++) { if (hw->vfbuf_use[i] == 0) break; } - return i == DECODE_BUFFER_NUM_MAX ? false : true; + return i == hw->buf_num ? false : true; } static int find_free_buffer(struct vdec_mjpeg_hw_s *hw) { int i; - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + for (i = 0; i < hw->buf_num; i++) { if (hw->vfbuf_use[i] == 0) break; } - if (i == DECODE_BUFFER_NUM_MAX) + if (i == hw->buf_num) return -1; if (hw->is_used_v4l) @@ -975,7 +990,7 @@ static int find_free_buffer(struct vdec_mjpeg_hw_s *hw) static int vmjpeg_hw_ctx_restore(struct vdec_mjpeg_hw_s *hw) { struct buffer_spec_s *buff_spec; - u32 index, i; + int index, i; index = find_free_buffer(hw); if (index < 0) @@ -988,7 +1003,7 @@ static int vmjpeg_hw_ctx_restore(struct vdec_mjpeg_hw_s *hw) vmjpeg_canvas_init(hw); } else { if (!hw->is_used_v4l) { - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + for (i = 0; i < hw->buf_num; i++) { buff_spec = &hw->buffer_spec[i]; canvas_config_config(buff_spec->y_canvas_index, &buff_spec->canvas_config[0]); @@ -1150,12 +1165,12 @@ static void run(struct vdec_s *vdec, unsigned long mask, hw->run_count++; vdec_reset_core(vdec); - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + for (i = 0; i < hw->buf_num; i++) { if (hw->vfbuf_use[i] == 0) break; } - if (i == DECODE_BUFFER_NUM_MAX) { + if (i == hw->buf_num) { hw->dec_result = DEC_RESULT_AGAIN; vdec_schedule_work(&hw->work); return; @@ -1395,14 +1410,13 @@ static int ammvdec_mjpeg_probe(struct platform_device *pdev) { struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; struct vdec_mjpeg_hw_s *hw = NULL; + int config_val = 0; if (pdata == NULL) { pr_info("ammvdec_mjpeg memory resource undefined.\n"); return -EFAULT; } - hw = (struct vdec_mjpeg_hw_s *)devm_kzalloc(&pdev->dev, - sizeof(struct vdec_mjpeg_hw_s), GFP_KERNEL); hw = vzalloc(sizeof(struct vdec_mjpeg_hw_s)); if (hw == NULL) { pr_info("\nammvdec_mjpeg device data allocation failed\n"); @@ -1436,6 +1450,19 @@ static int ammvdec_mjpeg_probe(struct platform_device *pdev) snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, PROVIDER_NAME ".%02x", pdev->id & 0xff); + if (((debug_enable & IGNORE_PARAM_FROM_CONFIG) == 0) && pdata->config_len) { + mmjpeg_debug_print(DECODE_ID(hw), 0, "pdata->config: %s\n", pdata->config); + if (get_config_int(pdata->config, "parm_v4l_buffer_margin", + &config_val) == 0) + hw->dynamic_buf_num_margin = config_val; + else + hw->dynamic_buf_num_margin = dynamic_buf_num_margin; + } else { + hw->dynamic_buf_num_margin = dynamic_buf_num_margin; + } + + hw->buf_num = vmjpeg_get_buf_num(hw); + vf_provider_init(&pdata->vframe_provider, pdata->vf_provider_name, &vf_provider_ops, pdata); @@ -1460,6 +1487,8 @@ static int ammvdec_mjpeg_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 { @@ -1559,6 +1588,8 @@ MODULE_PARM_DESC(pre_decode_buf_level, module_param(udebug_flag, uint, 0664); MODULE_PARM_DESC(udebug_flag, "\n amvdec_mmpeg12 udebug_flag\n"); +module_param(dynamic_buf_num_margin, uint, 0664); +MODULE_PARM_DESC(dynamic_buf_num_margin, "\n dynamic_buf_num_margin\n"); module_param(decode_timeout_val, uint, 0664); MODULE_PARM_DESC(decode_timeout_val, "\n ammvdec_mjpeg decode_timeout_val\n"); @@ -1568,6 +1599,9 @@ module_param_array(max_process_time, uint, &max_decode_instance_num, 0664); module_param(radr, uint, 0664); MODULE_PARM_DESC(radr, "\nradr\n"); +module_param(start_decode_buf_level, uint, 0664); +MODULE_PARM_DESC(start_decode_buf_level, "\nstart_decode_buf_level\n"); + module_param(rval, uint, 0664); MODULE_PARM_DESC(rval, "\nrval\n"); diff --git a/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c b/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c index 6643f41..6f78276 100644 --- a/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c +++ b/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c @@ -48,6 +48,7 @@ #include <linux/amlogic/media/codec_mm/configs.h> #include "../utils/firmware.h" #include "../utils/vdec_v4l2_buffer_ops.h" +#include "../utils/config_parser.h" #define MEM_NAME "codec_mmpeg12" @@ -92,8 +93,11 @@ #define SEQINFO_PROG 0x00010000 #define CCBUF_SIZE (5*1024) -#define VF_POOL_SIZE 32 -#define DECODE_BUFFER_NUM_MAX 8 +#define VF_POOL_SIZE 64 +#define DECODE_BUFFER_NUM_MAX 16 +#define DECODE_BUFFER_NUM_DEF 8 +#define MAX_BMMU_BUFFER_NUM (DECODE_BUFFER_NUM_MAX + 1) + #define PUT_INTERVAL (HZ/100) #define WORKSPACE_SIZE (4*SZ_64K) /*swap&ccbuf&matirx&MV*/ #define CTX_LMEM_SWAP_OFFSET 0 @@ -102,23 +106,23 @@ #define CTX_CO_MV_OFFSET (CTX_QUANT_MATRIX_OFFSET + 1*1024) #define CTX_DECBUF_OFFSET (CTX_CO_MV_OFFSET + 0x11000) -#define MAX_BMMU_BUFFER_NUM (DECODE_BUFFER_NUM_MAX + 1) #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 = 2; -static u32 stat; static u32 udebug_flag; static unsigned int radr; static unsigned int rval; static u32 without_display_mode; +static u32 dynamic_buf_num_margin; #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 @@ -237,6 +241,7 @@ struct vdec_mpeg12_hw_s { unsigned long int start_process_time; u32 last_vld_level; u32 eos; + struct pic_info_t pics[DECODE_BUFFER_NUM_MAX]; u32 canvas_spec[DECODE_BUFFER_NUM_MAX]; u64 lastpts64; @@ -300,6 +305,8 @@ struct vdec_mpeg12_hw_s { bool is_used_v4l; void *v4l2_ctx; bool v4l_params_parsed; + u32 buf_num; + u32 dynamic_buf_num_margin; }; static void vmpeg12_local_init(struct vdec_mpeg12_hw_s *hw); static int vmpeg12_hw_ctx_restore(struct vdec_mpeg12_hw_s *hw); @@ -329,6 +336,7 @@ unsigned int mpeg12_debug_mask = 0xff; #define PRINT_FLAG_USERDATA_DETAIL 0x2000 #define PRINT_FLAG_TIMEOUT_STATUS 0x4000 #define PRINT_FLAG_V4L_DETAIL 0x8000 +#define IGNORE_PARAM_FROM_CONFIG 0x8000000 @@ -384,7 +392,7 @@ static int vmpeg12_v4l_alloc_buff_config_canvas(struct vdec_mpeg12_hw_s *hw, int return 0; ret = vdec_v4l_get_buffer(hw->v4l2_ctx, &fb); - if (ret) { + if (ret < 0) { debug_print(DECODE_ID(hw), 0, "[%d] get fb fail.\n", ((struct aml_vcodec_ctx *) @@ -450,28 +458,40 @@ static int vmpeg12_v4l_alloc_buff_config_canvas(struct vdec_mpeg12_hw_s *hw, int } +static unsigned int vmpeg12_get_buf_num(struct vdec_mpeg12_hw_s *hw) +{ + unsigned int buf_num = DECODE_BUFFER_NUM_DEF; + + buf_num += hw->dynamic_buf_num_margin; + + if (buf_num > DECODE_BUFFER_NUM_MAX) + buf_num = DECODE_BUFFER_NUM_MAX; + + return buf_num; +} + static bool is_enough_free_buffer(struct vdec_mpeg12_hw_s *hw) { int i; - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + for (i = 0; i < hw->buf_num; i++) { if (hw->vfbuf_use[i] == 0) break; } - return i == DECODE_BUFFER_NUM_MAX ? false : true; + return (i == hw->buf_num) ? false : true; } static int find_free_buffer(struct vdec_mpeg12_hw_s *hw) { int i; - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + for (i = 0; i < hw->buf_num; i++) { if (hw->vfbuf_use[i] == 0) break; } - if (i == DECODE_BUFFER_NUM_MAX) + if (i == hw->buf_num) return -1; if (hw->is_used_v4l) @@ -484,12 +504,12 @@ static u32 spec_to_index(struct vdec_mpeg12_hw_s *hw, u32 spec) { u32 i; - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + for (i = 0; i < hw->buf_num; i++) { if (hw->canvas_spec[i] == spec) return i; } - return DECODE_BUFFER_NUM_MAX; + return hw->buf_num; } static void set_frame_info(struct vdec_mpeg12_hw_s *hw, struct vframe_s *vf) @@ -1174,7 +1194,7 @@ static void userdata_push_do_work(struct work_struct *work) reg = READ_VREG(AV_SCRATCH_J); - hw->userdata_wp_ctx = reg; + hw->userdata_wp_ctx = reg & (~(1<<16)); meta_info.flags = ((reg >> 30) << 1); meta_info.flags |= (VFORMAT_MPEG12 << 3); /* check top_field_first flag */ @@ -1376,11 +1396,6 @@ static int prepare_display_buf(struct vdec_mpeg12_hw_s *hw, if (hw->is_used_v4l) { vf->v4l_mem_handle = hw->pics[index].v4l_ref_buf_addr; - if (vdec_v4l_binding_fd_and_vf(vf->v4l_mem_handle, vf) < 0) { - debug_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, - "v4l: binding vf fail.\n"); - return -1; - } debug_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, "[%d] %s(), v4l mem handle: 0x%lx\n", ((struct aml_vcodec_ctx *)(hw->v4l2_ctx))->id, @@ -1519,7 +1534,7 @@ static int update_reference(struct vdec_mpeg12_hw_s *hw, hw->refs[0] = hw->refs[1]; hw->refs[1] = index; /* second pic do not output */ - index = DECODE_BUFFER_NUM_MAX; + index = hw->buf_num; } else { hw->vfbuf_use[hw->refs[0]]--; hw->refs[0] = hw->refs[1]; @@ -1599,7 +1614,7 @@ static irqreturn_t vmpeg12_isr_thread_fn(struct vdec_s *vdec, int irq) (info & FRAME_PICTURE_MASK) != FRAME_PICTURE) hw->first_i_frame_ready = 1; /* for field struct case*/ - if (index >= DECODE_BUFFER_NUM_MAX) { + if (index >= hw->buf_num) { debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, "mmpeg12: invalid buf index: %d\n", index); hw->dec_result = DEC_RESULT_ERROR; @@ -1632,15 +1647,15 @@ static irqreturn_t vmpeg12_isr_thread_fn(struct vdec_s *vdec, int irq) (struct aml_vcodec_ctx *)(hw->v4l2_ctx); if (ctx->param_sets_from_ucode && !hw->v4l_params_parsed) { - struct aml_vdec_pic_infos info; + struct aml_vdec_ps_infos ps; - info.visible_width = hw->frame_width; - info.visible_height = hw->frame_height; - info.coded_width = ALIGN(hw->frame_width, 64); - info.coded_height = ALIGN(hw->frame_height, 64); - info.dpb_size = MAX_BMMU_BUFFER_NUM - 1; + ps.visible_width = hw->frame_width; + ps.visible_height = hw->frame_height; + ps.coded_width = ALIGN(hw->frame_width, 64); + ps.coded_height = ALIGN(hw->frame_height, 64); + ps.dpb_size = hw->buf_num; hw->v4l_params_parsed = true; - vdec_v4l_set_pic_infos(ctx, &info); + vdec_v4l_set_ps_infos(ctx, &ps); } if (!ctx->v4l_codec_ready) @@ -1697,11 +1712,11 @@ static irqreturn_t vmpeg12_isr_thread_fn(struct vdec_s *vdec, int irq) } else { /* drop b frame before reference pic ready */ if (hw->refs[0] == -1) - index = DECODE_BUFFER_NUM_MAX; + index = hw->buf_num; } vmpeg12_save_hw_context(hw, reg); - if (index >= DECODE_BUFFER_NUM_MAX) { + if (index >= hw->buf_num) { if (hw->dec_num != 2) { debug_print(DECODE_ID(hw), 0, "mmpeg12: drop pic num %d, type %c, index %d, offset %x\n", @@ -1794,7 +1809,7 @@ static void flush_output(struct vdec_mpeg12_hw_s *hw) if (hw->dec_num < 2) return; - if (index >= 0 && index < DECODE_BUFFER_NUM_MAX) + if (index >= 0 && index < hw->buf_num) prepare_display_buf(hw, &hw->pics[index]); } @@ -2077,13 +2092,13 @@ static void vmpeg12_canvas_init(struct vdec_mpeg12_hw_s *hw) decbuf_size = 0x300000; } - for (i = 0; i < MAX_BMMU_BUFFER_NUM; i++) { + for (i = 0; i < hw->buf_num + 1; i++) { unsigned canvas; - if (i == (MAX_BMMU_BUFFER_NUM - 1)) /* SWAP&CCBUF&MATIRX&MV */ + if (i == hw->buf_num) /* SWAP&CCBUF&MATIRX&MV */ decbuf_size = WORKSPACE_SIZE; - if (hw->is_used_v4l && !(i == (MAX_BMMU_BUFFER_NUM - 1))) { + if (hw->is_used_v4l && !(i == hw->buf_num)) { continue; } else { ret = decoder_bmmu_box_alloc_buf_phy(hw->mm_blk_handle, i, @@ -2095,7 +2110,7 @@ static void vmpeg12_canvas_init(struct vdec_mpeg12_hw_s *hw) } } - if (i == (MAX_BMMU_BUFFER_NUM - 1)) { + if (i == hw->buf_num) { if (hw->ccbuf_phyAddress_is_remaped_nocache) codec_mm_unmap_phyaddr(hw->ccbuf_phyAddress_virt); hw->ccbuf_phyAddress_virt = NULL; @@ -2175,10 +2190,11 @@ static void vmpeg2_dump_state(struct vdec_s *vdec) debug_print(DECODE_ID(hw), 0, "====== %s\n", __func__); debug_print(DECODE_ID(hw), 0, - "width/height (%d/%d),i_first %d\n", + "width/height (%d/%d),i_first %d, buf_num %d\n", hw->frame_width, hw->frame_height, - hw->first_i_frame_ready + hw->first_i_frame_ready, + hw->buf_num ); 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", @@ -2193,7 +2209,7 @@ static void vmpeg2_dump_state(struct vdec_s *vdec) hw->input_empty ); - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + for (i = 0; i < hw->buf_num; i++) { debug_print(DECODE_ID(hw), 0, "index %d, used %d\n", i, hw->vfbuf_use[i]); } @@ -2360,16 +2376,16 @@ static void check_timer_func(unsigned long arg) static int vmpeg12_hw_ctx_restore(struct vdec_mpeg12_hw_s *hw) { - u32 index, i; + int index, i; index = find_free_buffer(hw); - if (index >= DECODE_BUFFER_NUM_MAX) + if (index < 0 || index >= hw->buf_num) return -1; if (!hw->init_flag) vmpeg12_canvas_init(hw); else { if (!hw->is_used_v4l) { WRITE_VREG(MREG_CO_MV_START, hw->buf_start); - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + for (i = 0; i < hw->buf_num; i++) { canvas_config_config(canvas_y(hw->canvas_spec[i]), &hw->canvas_config[i][0]); canvas_config_config(canvas_u(hw->canvas_spec[i]), @@ -2512,6 +2528,7 @@ static void vmpeg12_local_init(struct vdec_mpeg12_hw_s *hw) 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; } @@ -2784,6 +2801,7 @@ static int ammvdec_mpeg12_probe(struct platform_device *pdev) { struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; struct vdec_mpeg12_hw_s *hw = NULL; + int config_val = 0; pr_info("ammvdec_mpeg12 probe start.\n"); @@ -2830,6 +2848,23 @@ static int ammvdec_mpeg12_probe(struct platform_device *pdev) vf_provider_init(&pdata->vframe_provider, pdata->vf_provider_name, &vf_provider_ops, pdata); + if (((debug_enable & IGNORE_PARAM_FROM_CONFIG) == 0) && pdata->config_len) { + debug_print(DECODE_ID(hw), 0, "pdata->config: %s\n", pdata->config); + if (get_config_int(pdata->config, "parm_v4l_buffer_margin", + &config_val) == 0) + hw->dynamic_buf_num_margin = config_val; + else + hw->dynamic_buf_num_margin = dynamic_buf_num_margin; + } else { + hw->dynamic_buf_num_margin = dynamic_buf_num_margin; + } + hw->buf_num = vmpeg12_get_buf_num(hw); + + if (pdata->parallel_dec == 1) { + int i; + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) + hw->canvas_spec[i] = 0xffffff; + } platform_set_drvdata(pdev, pdata); hw->canvas_mode = pdata->canvas_mode; hw->platform_dev = pdev; @@ -2854,6 +2889,8 @@ static int ammvdec_mpeg12_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 { @@ -2983,12 +3020,20 @@ static struct codec_profile_t ammvdec_mpeg12_profile = { }; static struct mconfig mmpeg12_configs[] = { - MC_PU32("stat", &stat), MC_PU32("radr", &radr), MC_PU32("rval", &rval), 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), + MC_PU32("dynamic_buf_num_margin", &dynamic_buf_num_margin), +#ifdef AGAIN_HAS_THRESHOLD + MC_PU32("again_threshold", &again_threshold), +#endif }; static struct mconfig_node mmpeg12_node; @@ -3031,9 +3076,17 @@ MODULE_PARM_DESC(debug_enable, module_param(pre_decode_buf_level, int, 0664); MODULE_PARM_DESC(pre_decode_buf_level, "\n ammvdec_mpeg12 pre_decode_buf_level\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(decode_timeout_val, uint, 0664); MODULE_PARM_DESC(decode_timeout_val, "\n ammvdec_mpeg12 decode_timeout_val\n"); +module_param(dynamic_buf_num_margin, uint, 0664); +MODULE_PARM_DESC(dynamic_buf_num_margin, "\n ammvdec_mpeg12 dynamic_buf_num_margin\n"); + module_param_array(max_process_time, uint, &max_decode_instance_num, 0664); module_param(udebug_flag, uint, 0664); diff --git a/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c b/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c index 30e4072..c098a5e 100644 --- a/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c +++ b/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c @@ -46,6 +46,7 @@ #include <linux/amlogic/media/codec_mm/configs.h> #include "../utils/firmware.h" #include "../utils/vdec_v4l2_buffer_ops.h" +#include "../utils/config_parser.h" #define DRIVER_NAME "ammvdec_mpeg4" #define MODULE_NAME "ammvdec_mpeg4" @@ -91,8 +92,9 @@ /* values between 6 and 14 are reserved */ #define PARC_EXTENDED 15 -#define VF_POOL_SIZE 16 -#define DECODE_BUFFER_NUM_MAX 8 +#define VF_POOL_SIZE 64 +#define DECODE_BUFFER_NUM_MAX 16 +#define DECODE_BUFFER_NUM_DEF 8 #define PUT_INTERVAL (HZ/100) #define MAX_BMMU_BUFFER_NUM (DECODE_BUFFER_NUM_MAX + 1) #define WORKSPACE_SIZE (12*SZ_64K) @@ -135,16 +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; /* 0x40bit = 8byte */ static unsigned int frmbase_cont_bitlevel = 0x40; +static unsigned int dynamic_buf_num_margin; #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; @@ -167,6 +171,7 @@ unsigned int mpeg4_debug_mask = 0xff; #define PRINT_FLAG_VDEC_STATUS 0x0800 #define PRINT_FLAG_TIMEOUT_STATUS 0x1000 #define PRINT_FLAG_V4L_DETAIL 0x8000 +#define IGNORE_PARAM_FROM_CONFIG 0x8000000 int mmpeg4_debug_print(int index, int debug_flag, const char *fmt, ...) { @@ -298,6 +303,8 @@ struct vdec_mpeg4_hw_s { bool is_used_v4l; void *v4l2_ctx; bool v4l_params_parsed; + u32 buf_num; + u32 dynamic_buf_num_margin; }; static void vmpeg4_local_init(struct vdec_mpeg4_hw_s *hw); static int vmpeg4_hw_ctx_restore(struct vdec_mpeg4_hw_s *hw); @@ -331,6 +338,18 @@ static unsigned char aspect_ratio_table[16] = { static void reset_process_time(struct vdec_mpeg4_hw_s *hw); + +static int vmpeg4_get_buf_num(struct vdec_mpeg4_hw_s *hw) +{ + int buf_num = DECODE_BUFFER_NUM_DEF; + + buf_num += hw->dynamic_buf_num_margin; + if (buf_num > DECODE_BUFFER_NUM_MAX) + buf_num = DECODE_BUFFER_NUM_MAX; + + return buf_num; +} + static int vmpeg4_v4l_alloc_buff_config_canvas(struct vdec_mpeg4_hw_s *hw, int i) { int ret; @@ -345,7 +364,7 @@ static int vmpeg4_v4l_alloc_buff_config_canvas(struct vdec_mpeg4_hw_s *hw, int i return 0; ret = vdec_v4l_get_buffer(hw->v4l2_ctx, &fb); - if (ret) { + if (ret < 0) { mmpeg4_debug_print(DECODE_ID(hw), 0, "[%d] get fb fail.\n", ((struct aml_vcodec_ctx *) @@ -421,24 +440,24 @@ static bool is_enough_free_buffer(struct vdec_mpeg4_hw_s *hw) { int i; - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + for (i = 0; i < hw->buf_num; i++) { if (hw->vfbuf_use[i] == 0) break; } - return i == DECODE_BUFFER_NUM_MAX ? false : true; + return i == hw->buf_num ? false : true; } static int find_free_buffer(struct vdec_mpeg4_hw_s *hw) { int i; - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + for (i = 0; i < hw->buf_num; i++) { if (hw->vfbuf_use[i] == 0) break; } - if (i == DECODE_BUFFER_NUM_MAX) + if (i == hw->buf_num) return -1; if (hw->is_used_v4l) @@ -452,7 +471,7 @@ static int spec_to_index(struct vdec_mpeg4_hw_s *hw, u32 spec) { int i; - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + for (i = 0; i < hw->buf_num; i++) { if (hw->canvas_spec[i] == spec) return i; } @@ -717,11 +736,6 @@ static int prepare_display_buf(struct vdec_mpeg4_hw_s * hw, if (hw->is_used_v4l) { vf->v4l_mem_handle = hw->pic[index].v4l_ref_buf_addr; - if (vdec_v4l_binding_fd_and_vf(vf->v4l_mem_handle, vf) < 0) { - mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, - "v4l: binding vf fail.\n"); - return -1; - } mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, "[%d] %s(), v4l mem handle: 0x%lx\n", ((struct aml_vcodec_ctx *)(hw->v4l2_ctx))->id, @@ -909,7 +923,7 @@ static irqreturn_t vmpeg4_isr_thread_fn(struct vdec_s *vdec, int irq) READ_VREG(VIFF_BIT_CNT)); if (vdec_frame_based(vdec)) { - //vmpeg4_save_hw_context(hw); + vmpeg4_save_hw_context(hw); hw->dec_result = DEC_RESULT_DONE; vdec_schedule_work(&hw->work); } else { @@ -954,15 +968,15 @@ static irqreturn_t vmpeg4_isr_thread_fn(struct vdec_s *vdec, int irq) (struct aml_vcodec_ctx *)(hw->v4l2_ctx); if (ctx->param_sets_from_ucode && !hw->v4l_params_parsed) { - struct aml_vdec_pic_infos info; + struct aml_vdec_ps_infos ps; - info.visible_width = hw->frame_width; - info.visible_height = hw->frame_height; - info.coded_width = ALIGN(hw->frame_width, 64); - info.coded_height = ALIGN(hw->frame_height, 64); - info.dpb_size = MAX_BMMU_BUFFER_NUM - 1; + ps.visible_width = hw->frame_width; + ps.visible_height = hw->frame_height; + ps.coded_width = ALIGN(hw->frame_width, 64); + ps.coded_height = ALIGN(hw->frame_height, 64); + ps.dpb_size = hw->buf_num; hw->v4l_params_parsed = true; - vdec_v4l_set_pic_infos(ctx, &info); + vdec_v4l_set_ps_infos(ctx, &ps); } if (!ctx->v4l_codec_ready) @@ -1516,14 +1530,14 @@ static int vmpeg4_canvas_init(struct vdec_mpeg4_hw_s *hw) } } - for (i = 0; i < MAX_BMMU_BUFFER_NUM; i++) { + for (i = 0; i < hw->buf_num + 1; i++) { unsigned canvas; - if (i == (MAX_BMMU_BUFFER_NUM - 1)) + if (i == hw->buf_num) decbuf_size = WORKSPACE_SIZE; - if (hw->is_used_v4l && !(i == (MAX_BMMU_BUFFER_NUM - 1))) { + if (hw->is_used_v4l && !(i == hw->buf_num)) { continue; } else { ret = decoder_bmmu_box_alloc_buf_phy(hw->mm_blk_handle, i, @@ -1535,7 +1549,7 @@ static int vmpeg4_canvas_init(struct vdec_mpeg4_hw_s *hw) } } - if (i == (MAX_BMMU_BUFFER_NUM - 1)) { + if (i == hw->buf_num) { hw->buf_start = decbuf_start; } else { if (vdec->parallel_dec == 1) { @@ -1595,13 +1609,14 @@ static void vmpeg4_dump_state(struct vdec_s *vdec) mmpeg4_debug_print(DECODE_ID(hw), 0, "====== %s\n", __func__); mmpeg4_debug_print(DECODE_ID(hw), 0, - "width/height (%d/%d), i_fram:%d, buffer_not_ready %d\n", + "width/height (%d/%d), i_fram:%d, buffer_not_ready %d, buf_num %d\n", hw->frame_width, hw->frame_height, hw->first_i_frame_ready, - hw->buffer_not_ready + hw->buffer_not_ready, + hw->buf_num ); - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + for (i = 0; i < hw->buf_num; i++) { mmpeg4_debug_print(DECODE_ID(hw), 0, "index %d, used %d\n", i, hw->vfbuf_use[i]); } @@ -1795,7 +1810,7 @@ static int vmpeg4_hw_ctx_restore(struct vdec_mpeg4_hw_s *hw) return -1; } else { if (!hw->is_used_v4l) { - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + for (i = 0; i < hw->buf_num; i++) { canvas_config_config(canvas_y(hw->canvas_spec[i]), &hw->canvas_config[i][0]); canvas_config_config(canvas_u(hw->canvas_spec[i]), @@ -2239,6 +2254,7 @@ 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; + int config_val = 0; if (pdata == NULL) { pr_err("%s memory resource undefined.\n", __func__); @@ -2272,6 +2288,19 @@ static int ammvdec_mpeg4_probe(struct platform_device *pdev) snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, PROVIDER_NAME ".%02x", pdev->id & 0xff); + + if (((debug_enable & IGNORE_PARAM_FROM_CONFIG) == 0) && pdata->config_len) { + mmpeg4_debug_print(DECODE_ID(hw), 0, "pdata->config: %s\n", pdata->config); + if (get_config_int(pdata->config, "parm_v4l_buffer_margin", + &config_val) == 0) + hw->dynamic_buf_num_margin = config_val; + else + hw->dynamic_buf_num_margin = dynamic_buf_num_margin; + } else { + hw->dynamic_buf_num_margin = dynamic_buf_num_margin; + } + hw->buf_num = vmpeg4_get_buf_num(hw); + if (pdata->parallel_dec == 1) { int i; for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) @@ -2317,6 +2346,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); @@ -2433,6 +2463,9 @@ MODULE_PARM_DESC(debug_enable, module_param(frmbase_cont_bitlevel, uint, 0664); MODULE_PARM_DESC(frmbase_cont_bitlevel, "\nfrmbase_cont_bitlevel\n"); +module_param(dynamic_buf_num_margin, uint, 0664); +MODULE_PARM_DESC(dynamic_buf_num_margin, "\n dynamic_buf_num_margin\n"); + module_param(radr, uint, 0664); MODULE_PARM_DESC(radr, "\nradr\n"); @@ -2446,7 +2479,11 @@ 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"); diff --git a/drivers/frame_provider/decoder/utils/decoder_bmmu_box.c b/drivers/frame_provider/decoder/utils/decoder_bmmu_box.c index 590b812..461621b 100644 --- a/drivers/frame_provider/decoder/utils/decoder_bmmu_box.c +++ b/drivers/frame_provider/decoder/utils/decoder_bmmu_box.c @@ -41,6 +41,7 @@ struct decoder_bmmu_box { struct mutex mutex; struct list_head list; int total_size; + int box_ref_cnt; int change_size_on_need_smaller; int align2n; /*can overwite on idx alloc */ int mem_flags; /*can overwite on idx alloc */ @@ -78,6 +79,25 @@ static int decoder_bmmu_box_mgr_del_box(struct decoder_bmmu_box *box) return 0; } +bool decoder_bmmu_box_valide_check(void *box) +{ + struct decoder_bmmu_box_mgr *mgr = get_decoder_bmmu_box_mgr(); + struct decoder_bmmu_box *bmmu_box = NULL; + bool is_valide = false; + + mutex_lock(&mgr->mutex); + list_for_each_entry(bmmu_box, &mgr->box_list, list) { + if (bmmu_box && bmmu_box == box) { + is_valide = true; + break; + } + } + mutex_unlock(&mgr->mutex); + + return is_valide; +} +EXPORT_SYMBOL(decoder_bmmu_box_valide_check); + void *decoder_bmmu_box_alloc_box(const char *name, int channel_id, int max_num, int aligned, int mem_flags) @@ -169,6 +189,7 @@ int decoder_bmmu_box_alloc_idx(void *handle, int idx, int size, int aligned_2n, box->total_size += mm->buffer_size; mm->ins_id = box->channel_id; mm->ins_buffer_id = idx; + box->box_ref_cnt++; } } mutex_unlock(&box->mutex); @@ -193,6 +214,7 @@ int decoder_bmmu_box_free_idx(void *handle, int idx) codec_mm_release(mm, box->name); box->mm_list[idx] = NULL; mm = NULL; + box->box_ref_cnt--; } mutex_unlock(&box->mutex); return 0; @@ -224,6 +246,31 @@ int decoder_bmmu_box_free(void *handle) } EXPORT_SYMBOL(decoder_bmmu_box_free); +void decoder_bmmu_try_to_release_box(void *handle) +{ + struct decoder_bmmu_box *box = handle; + bool is_keep = false; + int i; + + if (!box || box->box_ref_cnt) + return; + + mutex_lock(&box->mutex); + for (i = 0; i < box->max_mm_num; i++) { + if (box->mm_list[i]) { + is_keep = true; + break; + } + } + mutex_unlock(&box->mutex); + + if (!is_keep) { + decoder_bmmu_box_mgr_del_box(box); + kfree(box); + } +} +EXPORT_SYMBOL(decoder_bmmu_try_to_release_box); + void *decoder_bmmu_box_get_mem_handle(void *box_handle, int idx) { struct decoder_bmmu_box *box = box_handle; diff --git a/drivers/frame_provider/decoder/utils/decoder_bmmu_box.h b/drivers/frame_provider/decoder/utils/decoder_bmmu_box.h index 8744da1..778cb8e 100644 --- a/drivers/frame_provider/decoder/utils/decoder_bmmu_box.h +++ b/drivers/frame_provider/decoder/utils/decoder_bmmu_box.h @@ -60,6 +60,9 @@ int decoder_bmmu_box_alloc_idx_wait( int mem_flags, int wait_flags); +bool decoder_bmmu_box_valide_check(void *box); +void decoder_bmmu_try_to_release_box(void *handle); + int decoder_bmmu_box_init(void); void decoder_bmmu_box_exit(void); diff --git a/drivers/frame_provider/decoder/utils/decoder_mmu_box.c b/drivers/frame_provider/decoder/utils/decoder_mmu_box.c index 5ab7c16..8389514 100644 --- a/drivers/frame_provider/decoder/utils/decoder_mmu_box.c +++ b/drivers/frame_provider/decoder/utils/decoder_mmu_box.c @@ -34,6 +34,7 @@ struct decoder_mmu_box { const char *name; int channel_id; int tvp_mode; + int box_ref_cnt; struct mutex mutex; struct list_head list; struct codec_mm_scatter *sc_list[1]; @@ -75,6 +76,51 @@ static int decoder_mmu_box_mgr_del_box(struct decoder_mmu_box *box) return 0; } +bool decoder_mmu_box_valide_check(void *box) +{ + struct decoder_mmu_box_mgr *mgr = get_decoder_mmu_box_mgr(); + struct decoder_mmu_box *mmu_box = NULL; + bool is_valide = false; + + mutex_lock(&mgr->mutex); + list_for_each_entry(mmu_box, &mgr->box_list, list) { + if (mmu_box && mmu_box == box) { + is_valide = true; + break; + } + } + mutex_unlock(&mgr->mutex); + + return is_valide; +} +EXPORT_SYMBOL(decoder_mmu_box_valide_check); + +void decoder_mmu_try_to_release_box(void *handle) +{ + struct decoder_mmu_box *box = handle; + bool is_keep = false; + int i; + + if (!box || box->box_ref_cnt) + return; + + mutex_lock(&box->mutex); + for (i = 0; i < box->max_sc_num; i++) { + if (box->sc_list[i]) { + is_keep = true; + break; + } + } + mutex_unlock(&box->mutex); + + if (!is_keep) { + decoder_mmu_box_mgr_del_box(box); + codec_mm_scatter_mgt_delay_free_swith(0, 0, 0, box->tvp_mode); + kfree(box); + } +} +EXPORT_SYMBOL(decoder_mmu_try_to_release_box); + int decoder_mmu_box_sc_check(void *handle, int is_tvp) { struct decoder_mmu_box *box = handle; @@ -159,6 +205,7 @@ int decoder_mmu_box_alloc_idx( return -1; } box->sc_list[idx] = sc; + box->box_ref_cnt++; } for (i = 0; i < num_pages; i++) @@ -209,7 +256,13 @@ int decoder_mmu_box_free_idx(void *handle, int idx) if (sc && sc->page_cnt > 0) { codec_mm_scatter_dec_owner_user(sc, 0); box->sc_list[idx] = NULL; - } mutex_unlock(&box->mutex); + box->box_ref_cnt--; + } + mutex_unlock(&box->mutex); + + if (sc && box->box_ref_cnt == 0) + codec_mm_scatter_mgt_delay_free_swith(0, 0, 0, box->tvp_mode); + return 0; } EXPORT_SYMBOL(decoder_mmu_box_free_idx); diff --git a/drivers/frame_provider/decoder/utils/decoder_mmu_box.h b/drivers/frame_provider/decoder/utils/decoder_mmu_box.h index 9f4e098..029f91a 100644 --- a/drivers/frame_provider/decoder/utils/decoder_mmu_box.h +++ b/drivers/frame_provider/decoder/utils/decoder_mmu_box.h @@ -42,6 +42,8 @@ int decoder_mmu_box_move_keep_idx(void *box_handle, int decoder_mmu_box_free_keep(int keep_id); int decoder_mmu_box_free_all_keep(void); void *decoder_mmu_box_get_mem_handle(void *box_handle, int idx); +bool decoder_mmu_box_valide_check(void *box); +void decoder_mmu_try_to_release_box(void *handle); int decoder_mmu_box_init(void); void decoder_mmu_box_exit(void); diff --git a/drivers/frame_provider/decoder/utils/vdec.c b/drivers/frame_provider/decoder/utils/vdec.c index 54f9051..41e84ba 100644 --- a/drivers/frame_provider/decoder/utils/vdec.c +++ b/drivers/frame_provider/decoder/utils/vdec.c @@ -33,6 +33,9 @@ #include <linux/amlogic/media/vfm/vframe_provider.h> #include <linux/amlogic/media/vfm/vframe_receiver.h> #include <linux/amlogic/media/video_sink/ionvideo_ext.h> +#ifdef CONFIG_AMLOGIC_V4L_VIDEO3 +#include <linux/amlogic/media/video_sink/v4lvideo_ext.h> +#endif #include <linux/amlogic/media/vfm/vfm_ext.h> /*for VDEC_DEBUG_SUPPORT*/ #include <linux/time.h> @@ -113,6 +116,9 @@ static DEFINE_SPINLOCK(vdec_spin_lock); #define DISABLE_FRAME_INFO 2 static int frameinfo_flag = 0; +static int v4lvideo_add_di = 1; +static int max_di_instance = 2; + //static int path_debug = 0; static struct vframe_qos_s *frame_info_buf_in = NULL; @@ -1558,6 +1564,7 @@ EXPORT_SYMBOL(vdec_set_flag); void vdec_set_eos(struct vdec_s *vdec, bool eos) { struct vdec_core_s *core = vdec_core; + vdec->input.eos = eos; if (vdec->slave) @@ -2203,12 +2210,64 @@ s32 vdec_init(struct vdec_s *vdec, int is_4k) snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE, "%s %s", vdec->vf_provider_name, "amvideo"); + snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE, + "vdec-map-%d", vdec->id); } else if (p->frame_base_video_path == FRAME_BASE_PATH_V4L_VIDEO) { snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE, "%s %s %s", vdec->vf_provider_name, vdec->vf_receiver_name, "amvideo"); snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE, "vdec-map-%d", vdec->id); + } else if (p->frame_base_video_path == + FRAME_BASE_PATH_DI_V4LVIDEO) { +#ifdef CONFIG_AMLOGIC_V4L_VIDEO3 + r = v4lvideo_assign_map(&vdec->vf_receiver_name, + &vdec->vf_receiver_inst); +#else + r = -1; +#endif + if (r < 0) { + pr_err("V4lVideo frame receiver allocation failed.\n"); + mutex_lock(&vdec_mutex); + inited_vcodec_num--; + mutex_unlock(&vdec_mutex); + goto error; + } + if (!v4lvideo_add_di || vdec_secure(vdec)) + snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE, + "%s %s", vdec->vf_provider_name, + vdec->vf_receiver_name); + else { + if (vdec->vf_receiver_inst == 0) + snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE, + "%s %s %s", vdec->vf_provider_name, + "dimulti.1", + vdec->vf_receiver_name); + else if ((vdec->vf_receiver_inst < + max_di_instance) && + (vdec->vf_receiver_inst == 1)) + snprintf(vdec->vfm_map_chain, + VDEC_MAP_NAME_SIZE, + "%s %s %s", + vdec->vf_provider_name, + "deinterlace", + vdec->vf_receiver_name); + else if (vdec->vf_receiver_inst < + max_di_instance) + snprintf(vdec->vfm_map_chain, + VDEC_MAP_NAME_SIZE, + "%s %s%d %s", + vdec->vf_provider_name, + "dimulti.", + vdec->vf_receiver_inst, + vdec->vf_receiver_name); + else + snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE, + "%s %s", vdec->vf_provider_name, + vdec->vf_receiver_name); + } + snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE, + "vdec-map-%d", vdec->id); } if (vfm_map_add(vdec->vfm_map_id, @@ -2419,6 +2478,59 @@ int vdec_reset(struct vdec_s *vdec) } EXPORT_SYMBOL(vdec_reset); +int vdec_v4l2_reset(struct vdec_s *vdec, int flag) +{ + //trace_vdec_reset(vdec); /*DEBUG_TMP*/ + pr_debug("vdec_v4l2_reset %d\n", flag); + vdec_disconnect(vdec); + if (flag != 2) { + if (vdec->vframe_provider.name) + vf_unreg_provider(&vdec->vframe_provider); + + if ((vdec->slave) && (vdec->slave->vframe_provider.name)) + vf_unreg_provider(&vdec->slave->vframe_provider); + + if (vdec->reset) { + vdec->reset(vdec); + if (vdec->slave) + vdec->slave->reset(vdec->slave); + } + vdec->mc_loaded = 0;/*clear for reload firmware*/ + + vdec_input_release(&vdec->input); + + vdec_input_init(&vdec->input, vdec); + + vdec_input_prepare_bufs(&vdec->input, vdec->sys_info->width, + vdec->sys_info->height); + + vf_reg_provider(&vdec->vframe_provider); + vf_notify_receiver(vdec->vf_provider_name, + VFRAME_EVENT_PROVIDER_START, vdec); + + if (vdec->slave) { + vf_reg_provider(&vdec->slave->vframe_provider); + vf_notify_receiver(vdec->slave->vf_provider_name, + VFRAME_EVENT_PROVIDER_START, vdec->slave); + vdec->slave->mc_loaded = 0;/*clear for reload firmware*/ + } + } else { + if (vdec->reset) { + vdec->reset(vdec); + if (vdec->slave) + vdec->slave->reset(vdec->slave); + } + } + + vdec_connect(vdec); + + vdec_frame_check_init(vdec); + + return 0; +} +EXPORT_SYMBOL(vdec_v4l2_reset); + + void vdec_free_cmabuf(void) { mutex_lock(&vdec_mutex); @@ -2647,6 +2759,7 @@ unsigned long vdec_ready_to_run(struct vdec_s *vdec, unsigned long mask) inc_profi_count(mask, vdec->check_count); #endif if (vdec_core_with_input(mask)) { + /* check frame based input underrun */ if (input && !input->eos && input_frame_based(input) && (!vdec_input_next_chunk(input))) { @@ -3744,7 +3857,7 @@ void vdec_reset_core(struct vdec_s *vdec) */ if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_TL1)) { - WRITE_VREG(DOS_SW_RESET0, (1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)); + WRITE_VREG(DOS_SW_RESET0, (1<<3)|(1<<4)|(1<<5)|(1<<7)|(1<<8)|(1<<9)); } else { WRITE_VREG(DOS_SW_RESET0, (1<<3)|(1<<4)|(1<<5)); @@ -5081,6 +5194,14 @@ module_param(disable_switch_single_to_mult, int, 0664); module_param(frameinfo_flag, int, 0664); MODULE_PARM_DESC(frameinfo_flag, "\n frameinfo_flag\n"); +module_param(v4lvideo_add_di, int, 0664); +MODULE_PARM_DESC(v4lvideo_add_di, + "\n v4lvideo_add_di\n"); + +module_param(max_di_instance, int, 0664); +MODULE_PARM_DESC(max_di_instance, + "\n max_di_instance\n"); + /* *module_init(vdec_module_init); *module_exit(vdec_module_exit); diff --git a/drivers/frame_provider/decoder/utils/vdec.h b/drivers/frame_provider/decoder/utils/vdec.h index 80fa8dc..59ee2db 100644 --- a/drivers/frame_provider/decoder/utils/vdec.h +++ b/drivers/frame_provider/decoder/utils/vdec.h @@ -360,6 +360,8 @@ extern int vdec_destroy(struct vdec_s *vdec); /* reset vdec */ extern int vdec_reset(struct vdec_s *vdec); +extern int vdec_v4l2_reset(struct vdec_s *vdec, int flag); + extern void vdec_set_status(struct vdec_s *vdec, int status); extern void vdec_set_next_status(struct vdec_s *vdec, int status); diff --git a/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c b/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c index 763d62e..107efec 100644 --- a/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c +++ b/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c @@ -1,119 +1,64 @@ -#include <linux/file.h> -#include <linux/anon_inodes.h> #include "vdec_v4l2_buffer_ops.h" -const struct file_operations v4l2_file_fops = {}; - -static int is_v4l2_buf_file(struct file *file) -{ - return file->f_op == &v4l2_file_fops; -} - -static int vdec_v4l_alloc_fd(void) -{ - int fd; - struct file *file = NULL; - - fd = get_unused_fd_flags(O_CLOEXEC); - if (fd < 0) { - pr_err("v4l: get unused fd fail\n"); - return fd; - } - - file = anon_inode_getfile("v4l2_meta_file", &v4l2_file_fops, NULL, 0); - if (IS_ERR(file)) { - put_unused_fd(fd); - pr_err("v4l: get file faill\n"); - return PTR_ERR(file); - } - - fd_install(fd, file); - - pr_info("v4l: fd %d, file %p, data %p\n", - fd, file, file->private_data); - - return fd; -} - -static int vdec_v4l_fd_install_data(int fd, void *data) +int vdec_v4l_get_buffer(struct aml_vcodec_ctx *ctx, + struct vdec_v4l2_buffer **out) { - struct file *file; + int ret = -1; - file = fget(fd); - - if (!file) { - pr_info("v4l: fget fd %d fail!, comm %s, pid %d\n", - fd, current->comm, current->pid); - return -EBADF; - } - - if (!is_v4l2_buf_file(file)) { - pr_info("v4l: v4l2 check fd fail!\n"); - return -EBADF; - } + if (ctx->drv_handle == 0) + return -EIO; - file->private_data = data; + ret = ctx->dec_if->get_param(ctx->drv_handle, + GET_PARAM_FREE_FRAME_BUFFER, out); - return 0; + return ret; } +EXPORT_SYMBOL(vdec_v4l_get_buffer); -int vdec_v4l_binding_fd_and_vf(ulong v4l_handle, void *vf) +int vdec_v4l_set_ps_infos(struct aml_vcodec_ctx *ctx, + struct aml_vdec_ps_infos *ps) { - int ret = 0, fd = -1; - struct vdec_v4l2_buffer *v4l_buf = - (struct vdec_v4l2_buffer *) v4l_handle; - - if (v4l_buf->m.vf_fd > 0) - return 0; - - fd = vdec_v4l_alloc_fd(); - if (fd < 0) { - pr_err("v4l: alloc fd fail %d.\n", fd); - return fd; - } + int ret = 0; - ret = vdec_v4l_fd_install_data(fd, vf); - if (ret < 0) { - put_unused_fd(fd); - pr_err("v4l: fd install data fail %d.\n", ret); - return ret; - } + if (ctx->drv_handle == 0) + return -EIO; - v4l_buf->m.vf_fd = fd; + ret = ctx->dec_if->set_param(ctx->drv_handle, + SET_PARAM_PS_INFO, ps); - return 0; + return ret; } -EXPORT_SYMBOL(vdec_v4l_binding_fd_and_vf); +EXPORT_SYMBOL(vdec_v4l_set_ps_infos); -int vdec_v4l_get_buffer(struct aml_vcodec_ctx *ctx, - struct vdec_v4l2_buffer **out) +int vdec_v4l_set_hdr_infos(struct aml_vcodec_ctx *ctx, + struct aml_vdec_hdr_infos *hdr) { int ret = 0; if (ctx->drv_handle == 0) return -EIO; - ret = ctx->dec_if->get_param(ctx->drv_handle, - GET_PARAM_FREE_FRAME_BUFFER, out); + ret = ctx->dec_if->set_param(ctx->drv_handle, + SET_PARAM_HDR_INFO, hdr); return ret; } -EXPORT_SYMBOL(vdec_v4l_get_buffer); +EXPORT_SYMBOL(vdec_v4l_set_hdr_infos); -int vdec_v4l_set_pic_infos(struct aml_vcodec_ctx *ctx, - struct aml_vdec_pic_infos *info) +int vdec_v4l_post_evet(struct aml_vcodec_ctx *ctx, u32 event) { int ret = 0; if (ctx->drv_handle == 0) return -EIO; - + if (event == 1) + ctx->reset_flag = 2; ret = ctx->dec_if->set_param(ctx->drv_handle, - SET_PARAM_PIC_INFO, info); + SET_PARAM_POST_EVENT, &event); return ret; } -EXPORT_SYMBOL(vdec_v4l_set_pic_infos); +EXPORT_SYMBOL(vdec_v4l_post_evet); int vdec_v4l_write_frame_sync(struct aml_vcodec_ctx *ctx) { diff --git a/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.h b/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.h index 6227a8b..13f3543 100644 --- a/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.h +++ b/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.h @@ -8,15 +8,19 @@ int vdec_v4l_get_buffer( struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer **out); -int vdec_v4l_set_pic_infos( +int vdec_v4l_set_ps_infos( struct aml_vcodec_ctx *ctx, - struct aml_vdec_pic_infos *info); + struct aml_vdec_ps_infos *ps); + +int vdec_v4l_set_hdr_infos( + struct aml_vcodec_ctx *ctx, + struct aml_vdec_hdr_infos *hdr); int vdec_v4l_write_frame_sync( struct aml_vcodec_ctx *ctx); -int vdec_v4l_binding_fd_and_vf( - ulong v4l_handle, - void *vf); +int vdec_v4l_post_evet( + struct aml_vcodec_ctx *ctx, + u32 event); #endif diff --git a/drivers/frame_provider/decoder/vp9/vvp9.c b/drivers/frame_provider/decoder/vp9/vvp9.c index 076d00d..6db0aa3 100644 --- a/drivers/frame_provider/decoder/vp9/vvp9.c +++ b/drivers/frame_provider/decoder/vp9/vvp9.c @@ -58,6 +58,7 @@ #include "../utils/firmware.h" #include "../../../common/chips/decoder_cpu_ver_info.h" #include "../utils/vdec_v4l2_buffer_ops.h" +#include <media/v4l2-mem2mem.h> #define MIX_STREAM_SUPPORT @@ -291,6 +292,9 @@ struct BUF_s { unsigned int free_start_adr; ulong v4l_ref_buf_addr; + ulong header_addr; + u32 header_size; + u32 luma_size; } /*BUF_t */; struct MVBUF_s { @@ -577,6 +581,8 @@ struct PIC_BUFFER_CONFIG_s { int max_mv; int min_mv; int avg_mv; + + bool vframe_bound; } PIC_BUFFER_CONFIG; enum BITSTREAM_PROFILE { @@ -1183,6 +1189,8 @@ struct VP9Decoder_s { int frameinfo_enable; struct vframe_qos_s vframe_qos; u32 mem_map_mode; + u32 dynamic_buf_num_margin; + struct vframe_s vframe_dummy; }; static int vp9_print(struct VP9Decoder_s *pbi, @@ -1221,8 +1229,8 @@ static int is_oversize(int w, int h) return false; } -static int config_pic(struct VP9Decoder_s *pbi, - struct PIC_BUFFER_CONFIG_s *pic_config); +static int v4l_alloc_and_config_pic(struct VP9Decoder_s *pbi, + struct PIC_BUFFER_CONFIG_s *pic); static void resize_context_buffers(struct VP9Decoder_s *pbi, struct VP9_Common_s *cm, int width, int height) @@ -1235,26 +1243,6 @@ static void resize_context_buffers(struct VP9Decoder_s *pbi, } pr_info("%s (%d,%d)=>(%d,%d)\r\n", __func__, cm->width, cm->height, width, height); - - if (pbi->is_used_v4l) { - struct PIC_BUFFER_CONFIG_s *pic = &cm->cur_frame->buf; - - /* resolution change happend need to reconfig buffs if true. */ - if (pic->y_crop_width != width || pic->y_crop_height != height) { - int i; - for (i = 0; i < pbi->used_buf_num; i++) { - pic = &cm->buffer_pool->frame_bufs[i].buf; - pic->y_crop_width = width; - pic->y_crop_height = height; - if (!config_pic(pbi, pic)) - set_canvas(pbi, pic); - else - vp9_print(pbi, 0, - "v4l: reconfig buff fail.\n"); - } - } - } - cm->width = width; cm->height = height; } @@ -1754,6 +1742,13 @@ static int alloc_mv_buf(struct VP9Decoder_s *pbi, int i, int size) { int ret = 0; + + if (pbi->m_mv_BUF[i].start_adr && + size > pbi->m_mv_BUF[i].size) { + dealloc_mv_bufs(pbi); + } else if (pbi->m_mv_BUF[i].start_adr) + return 0; + if (decoder_bmmu_box_alloc_buf_phy (pbi->bmmu_box, MV_BUFFER_IDX(i), size, @@ -2148,7 +2143,6 @@ static int get_free_fb(struct VP9Decoder_s *pbi) { struct VP9_Common_s *const cm = &pbi->common; struct RefCntBuffer_s *const frame_bufs = cm->buffer_pool->frame_bufs; - struct PIC_BUFFER_CONFIG_s *pic = NULL; int i; unsigned long flags; @@ -2162,21 +2156,11 @@ static int get_free_fb(struct VP9Decoder_s *pbi) } } for (i = 0; i < pbi->used_buf_num; ++i) { - pic = &frame_bufs[i].buf; if ((frame_bufs[i].ref_count == 0) && - (pic->vf_ref == 0) && (pic->index != -1)) { - if (pbi->is_used_v4l && !pic->cma_alloc_addr) { - pic->y_crop_width = pbi->frame_width; - pic->y_crop_height = pbi->frame_height; - if (!config_pic(pbi, pic)) { - set_canvas(pbi, pic); - init_pic_list_hw(pbi); - } else - i = pbi->used_buf_num; - } - + (frame_bufs[i].buf.vf_ref == 0) && + (frame_bufs[i].buf.index != -1) + ) break; - } } if (i != pbi->used_buf_num) { frame_bufs[i].ref_count = 1; @@ -2192,6 +2176,58 @@ static int get_free_fb(struct VP9Decoder_s *pbi) return i; } +static int v4l_get_free_fb(struct VP9Decoder_s *pbi) +{ + struct VP9_Common_s *const cm = &pbi->common; + struct RefCntBuffer_s *const frame_bufs = cm->buffer_pool->frame_bufs; + struct aml_vcodec_ctx * v4l = pbi->v4l2_ctx; + struct v4l_buff_pool *pool = &v4l->cap_pool; + struct PIC_BUFFER_CONFIG_s *pic = NULL; + int i, idx = INVALID_IDX; + ulong flags; + + lock_buffer_pool(cm->buffer_pool, flags); + + for (i = 0; i < pool->in; ++i) { + u32 state = (pool->seq[i] >> 16); + u32 index = (pool->seq[i] & 0xffff); + + switch (state) { + case V4L_CAP_BUFF_IN_DEC: + pic = &frame_bufs[i].buf; + if ((frame_bufs[i].ref_count == 0) && + (pic->vf_ref == 0) && + (pic->index != -1) && + pic->cma_alloc_addr) { + idx = i; + } + break; + case V4L_CAP_BUFF_IN_M2M: + pic = &frame_bufs[index].buf; + pic->y_crop_width = pbi->frame_width; + pic->y_crop_height = pbi->frame_height; + if (!v4l_alloc_and_config_pic(pbi, pic)) { + set_canvas(pbi, pic); + init_pic_list_hw(pbi); + idx = index; + } + break; + default: + pr_err("v4l buffer state err %d.\n", state); + break; + } + + if (idx != INVALID_IDX) { + frame_bufs[idx].ref_count = 1; + break; + } + } + + unlock_buffer_pool(cm->buffer_pool, flags); + + return idx; +} + static int get_free_buf_count(struct VP9Decoder_s *pbi) { struct VP9_Common_s *const cm = &pbi->common; @@ -2353,7 +2389,9 @@ int vp9_bufmgr_process(struct VP9Decoder_s *pbi, union param_u *params) if (debug & VP9_DEBUG_BUFMGR_DETAIL) dump_pic_list(pbi); #endif - cm->new_fb_idx = get_free_fb(pbi); + cm->new_fb_idx = pbi->is_used_v4l ? + v4l_get_free_fb(pbi) : + get_free_fb(pbi); if (cm->new_fb_idx == INVALID_IDX) { pr_info("get_free_fb error\r\n"); return -1; @@ -4648,12 +4686,64 @@ void adapt_coef_probs(int pic_count, int prev_kf, int cur_kf, int pre_fc, } +static bool v4l_is_there_vframe_bound(struct VP9Decoder_s *pbi) +{ + int i; + struct VP9_Common_s *const cm = &pbi->common; + struct RefCntBuffer_s *frame_bufs = cm->buffer_pool->frame_bufs; + + for (i = 0; i < pbi->used_buf_num; ++i) { + if (frame_bufs[i].buf.vframe_bound) + return true; + } + + return false; +} + +static void v4l_mmu_buffer_release(struct VP9Decoder_s *pbi) +{ + struct VP9_Common_s *const cm = &pbi->common; + struct RefCntBuffer_s *frame_bufs = cm->buffer_pool->frame_bufs; + int i; + + /* release workspace */ + if (pbi->bmmu_box) + decoder_bmmu_box_free_idx(pbi->bmmu_box, + WORK_SPACE_BUF_ID); + /* + * it's only when vframe get back to driver, right now we can be sure + * that vframe and fd are related. if the playback exits, the capture + * requires the upper app to release when the fd is closed, and others + * buffers drivers are released by driver. + */ + for (i = 0; i < pbi->used_buf_num; ++i) { + if (!frame_bufs[i].buf.vframe_bound) { + if (pbi->bmmu_box) + decoder_bmmu_box_free_idx(pbi->bmmu_box, + HEADER_BUFFER_IDX(i)); + if (pbi->mmu_box) + decoder_mmu_box_free_idx(pbi->mmu_box, i); + + vp9_print(pbi, PRINT_FLAG_V4L_DETAIL, + "%s free buffer[%d], bmmu_box: %p, mmu_box: %p\n", + __func__, i, pbi->bmmu_box, pbi->mmu_box); + } + } +} static void uninit_mmu_buffers(struct VP9Decoder_s *pbi) { #ifndef MV_USE_FIXED_BUF dealloc_mv_bufs(pbi); #endif + if (pbi->is_used_v4l && + v4l_is_there_vframe_bound(pbi)) { + if (get_double_write_mode(pbi) != 0x10) { + v4l_mmu_buffer_release(pbi); + return; + } + } + if (pbi->mmu_box) decoder_mmu_box_free(pbi->mmu_box); pbi->mmu_box = NULL; @@ -4663,14 +4753,118 @@ static void uninit_mmu_buffers(struct VP9Decoder_s *pbi) pbi->bmmu_box = NULL; } +static int calc_luc_quantity(u32 w, u32 h) +{ + int lcu_size = 64; /*fixed 64*/ + int pic_width_64 = (w + 63) & (~0x3f); + int pic_height_32 = (h + 31) & (~0x1f); + int pic_width_lcu = (pic_width_64 % lcu_size) ? + pic_width_64 / lcu_size + 1 : pic_width_64 / lcu_size; + int pic_height_lcu = (pic_height_32 % lcu_size) ? + pic_height_32 / lcu_size + 1 : pic_height_32 / lcu_size; + + return pic_width_lcu * pic_height_lcu; +} + +static int v4l_alloc_and_config_pic(struct VP9Decoder_s *pbi, + struct PIC_BUFFER_CONFIG_s *pic) +{ + int ret = -1; + int i = pic->index; + int dw_mode = get_double_write_mode_init(pbi); + int lcu_total = calc_luc_quantity(pbi->frame_width, pbi->frame_height); +#ifdef MV_USE_FIXED_BUF + u32 mpred_mv_end = pbi->work_space_buf->mpred_mv.buf_start + + pbi->work_space_buf->mpred_mv.buf_size; +#endif + struct vdec_v4l2_buffer *fb = NULL; + + ret = vdec_v4l_get_buffer(pbi->v4l2_ctx, &fb); + if (ret < 0) { + vp9_print(pbi, 0, "[%d] VP9 get buffer fail.\n", + ((struct aml_vcodec_ctx *) (pbi->v4l2_ctx))->id); + return ret; + } + + if (pbi->mmu_enable) { + pbi->m_BUF[i].header_addr = decoder_bmmu_box_get_phy_addr( + pbi->bmmu_box, HEADER_BUFFER_IDX(i)); + if (debug & VP9_DEBUG_BUFMGR_MORE) { + pr_info("MMU header_adr %d: %ld\n", + i, pbi->m_BUF[i].header_addr); + } + } + +#ifdef MV_USE_FIXED_BUF + if ((pbi->work_space_buf->mpred_mv.buf_start + + (((i + 1) * lcu_total) * MV_MEM_UNIT)) + <= mpred_mv_end) { +#endif + pbi->m_BUF[i].v4l_ref_buf_addr = (ulong)fb; + pic->cma_alloc_addr = fb->m.mem[0].addr; + if (fb->num_planes == 1) { + pbi->m_BUF[i].start_adr = fb->m.mem[0].addr; + pbi->m_BUF[i].size = fb->m.mem[0].size; + pbi->m_BUF[i].luma_size = fb->m.mem[0].offset; + fb->m.mem[0].bytes_used = fb->m.mem[0].size; + } else if (fb->num_planes == 2) { + pbi->m_BUF[i].start_adr = fb->m.mem[0].addr; + pbi->m_BUF[i].size = fb->m.mem[0].size + fb->m.mem[1].size; + pbi->m_BUF[i].luma_size = fb->m.mem[0].size; + fb->m.mem[0].bytes_used = fb->m.mem[0].size; + fb->m.mem[1].bytes_used = fb->m.mem[1].size; + } + + /* config frame buffer */ + if (pbi->mmu_enable) + pic->header_adr = pbi->m_BUF[i].header_addr; + + pic->BUF_index = i; + pic->lcu_total = lcu_total; + pic->mc_canvas_y = pic->index; + pic->mc_canvas_u_v = pic->index; + + if (dw_mode & 0x10) { + pic->dw_y_adr = pbi->m_BUF[i].start_adr; + pic->dw_u_v_adr = pic->dw_y_adr + pbi->m_BUF[i].luma_size; + pic->mc_canvas_y = (pic->index << 1); + pic->mc_canvas_u_v = (pic->index << 1) + 1; + } else if (dw_mode) { + pic->dw_y_adr = pbi->m_BUF[i].start_adr; + pic->dw_u_v_adr = pic->dw_y_adr + pbi->m_BUF[i].luma_size; + } + +#ifdef MV_USE_FIXED_BUF + pic->mpred_mv_wr_start_addr = + pbi->work_space_buf->mpred_mv.buf_start + + ((pic->index * lcu_total) * MV_MEM_UNIT); +#endif + if (debug) { + pr_info("%s index %d BUF_index %d ", + __func__, pic->index, + pic->BUF_index); + pr_info("comp_body_size %x comp_buf_size %x ", + pic->comp_body_size, + pic->buf_size); + pr_info("mpred_mv_wr_start_adr %ld\n", + pic->mpred_mv_wr_start_addr); + pr_info("dw_y_adr %d, pic_config->dw_u_v_adr =%d\n", + pic->dw_y_adr, + pic->dw_u_v_adr); + } +#ifdef MV_USE_FIXED_BUF + } +#endif + return ret; +} static int config_pic(struct VP9Decoder_s *pbi, struct PIC_BUFFER_CONFIG_s *pic_config) { int ret = -1; int i; - int pic_width = pbi->is_used_v4l ? pbi->frame_width : pbi->init_pic_w; - int pic_height = pbi->is_used_v4l ? pbi->frame_height : pbi->init_pic_h; + int pic_width = pbi->init_pic_w; + int pic_height = pbi->init_pic_h; int lcu_size = 64; /*fixed 64*/ int pic_width_64 = (pic_width + 63) & (~0x3f); int pic_height_32 = (pic_height + 31) & (~0x1f); @@ -4698,9 +4892,6 @@ static int config_pic(struct VP9Decoder_s *pbi, int mc_buffer_size_u_v = 0; int mc_buffer_size_u_v_h = 0; int dw_mode = get_double_write_mode_init(pbi); - int pic_width_align = 0; - int pic_height_align = 0; - struct vdec_v4l2_buffer *fb = NULL; pbi->lcu_total = lcu_total; @@ -4724,11 +4915,6 @@ static int config_pic(struct VP9Decoder_s *pbi, /*64k alignment*/ buf_size = ((mc_buffer_size_u_v_h << 16) * 3); buf_size = ((buf_size + 0xffff) >> 16) << 16; - - if (pbi->is_used_v4l) { - pic_width_align = ALIGN(pic_width_dw, 32); - pic_height_align = ALIGN(pic_height_dw, 32); - } } if (mc_buffer_size & 0xffff) /*64k alignment*/ @@ -4754,35 +4940,17 @@ static int config_pic(struct VP9Decoder_s *pbi, ) { #endif if (buf_size > 0) { - if (pbi->is_used_v4l) { - ret = vdec_v4l_get_buffer(pbi->v4l2_ctx, &fb); - if (ret) { - vp9_print(pbi, PRINT_FLAG_V4L_DETAIL, - "[%d] get fb fail.\n", - ((struct aml_vcodec_ctx *) - (pbi->v4l2_ctx))->id); - return ret; - } - - pbi->m_BUF[i].v4l_ref_buf_addr = (ulong)fb; - pic_config->cma_alloc_addr = fb->m.mem[0].addr; - vp9_print(pbi, PRINT_FLAG_V4L_DETAIL, - "[%d] %s(), v4l ref buf addr: 0x%x\n", - ((struct aml_vcodec_ctx *) - (pbi->v4l2_ctx))->id, __func__, fb); - } else { - ret = decoder_bmmu_box_alloc_buf_phy(pbi->bmmu_box, - VF_BUFFER_IDX(i), - buf_size, DRIVER_NAME, - &pic_config->cma_alloc_addr); - if (ret < 0) { - pr_info( - "decoder_bmmu_box_alloc_buf_phy idx %d size %d fail\n", - VF_BUFFER_IDX(i), - buf_size - ); - return ret; - } + ret = decoder_bmmu_box_alloc_buf_phy(pbi->bmmu_box, + VF_BUFFER_IDX(i), + buf_size, DRIVER_NAME, + &pic_config->cma_alloc_addr); + if (ret < 0) { + pr_info( + "decoder_bmmu_box_alloc_buf_phy idx %d size %d fail\n", + VF_BUFFER_IDX(i), + buf_size + ); + return ret; } if (pic_config->cma_alloc_addr) @@ -4808,27 +4976,9 @@ static int config_pic(struct VP9Decoder_s *pbi, pic_config->mc_canvas_y = pic_config->index; pic_config->mc_canvas_u_v = pic_config->index; if (dw_mode & 0x10) { - if (pbi->is_used_v4l) { - if (fb->num_planes == 1) { - fb->m.mem[0].bytes_used = - pic_width_align * pic_height_align; - pic_config->dw_y_adr = y_adr; - pic_config->dw_u_v_adr = y_adr + - fb->m.mem[0].bytes_used; - } else if (fb->num_planes == 2) { - fb->m.mem[0].bytes_used = - pic_width_align * pic_height_align; - fb->m.mem[1].bytes_used = - fb->m.mem[1].size; - pic_config->dw_y_adr = y_adr; - pic_config->dw_u_v_adr = y_adr + - fb->m.mem[0].bytes_used; - } - } else { - pic_config->dw_y_adr = y_adr; - pic_config->dw_u_v_adr = y_adr + - ((mc_buffer_size_u_v_h << 16) << 1); - } + pic_config->dw_y_adr = y_adr; + pic_config->dw_u_v_adr = y_adr + + ((mc_buffer_size_u_v_h << 16) << 1); pic_config->mc_canvas_y = (pic_config->index << 1); @@ -6401,8 +6551,6 @@ static int vp9_local_init(struct VP9Decoder_s *pbi) pbi->vvp9_amstream_dec_info.height : pbi->work_space_buf->max_height)); - pbi->mem_map_mode = mem_map_mode ? mem_map_mode : 0; - /* video is not support unaligned with 64 in tl1 ** vdec canvas mode will be linear when dump yuv is set */ @@ -6427,8 +6575,12 @@ static int vp9_local_init(struct VP9Decoder_s *pbi) #endif if (pbi->save_buffer_mode) pbi->used_buf_num = MAX_BUF_NUM_SAVE_BUF; - else - pbi->used_buf_num = max_buf_num; + else { + if (pbi->is_used_v4l) + pbi->used_buf_num = 5 + pbi->dynamic_buf_num_margin; + else + pbi->used_buf_num = max_buf_num; + } if (pbi->used_buf_num > MAX_BUF_NUM) pbi->used_buf_num = MAX_BUF_NUM; @@ -6566,10 +6718,10 @@ static void set_canvas(struct VP9Decoder_s *pbi, canvas_config_ex(pic_config->y_canvas_index, pic_config->dw_y_adr, canvas_w, canvas_h, - CANVAS_ADDR_NOWRAP, blkmode, 0x7); + CANVAS_ADDR_NOWRAP, blkmode, pbi->is_used_v4l ? 0 : 7); canvas_config_ex(pic_config->uv_canvas_index, pic_config->dw_u_v_adr, canvas_w, canvas_h, - CANVAS_ADDR_NOWRAP, blkmode, 0x7); + CANVAS_ADDR_NOWRAP, blkmode, pbi->is_used_v4l ? 0 : 7); #ifdef MULTI_INSTANCE_SUPPORT pic_config->canvas_config[0].phy_addr = @@ -6580,7 +6732,7 @@ static void set_canvas(struct VP9Decoder_s *pbi, canvas_h; pic_config->canvas_config[0].block_mode = blkmode; - pic_config->canvas_config[0].endian = 7; + pic_config->canvas_config[0].endian = pbi->is_used_v4l ? 0 : 7; pic_config->canvas_config[1].phy_addr = pic_config->dw_u_v_adr; @@ -6590,7 +6742,7 @@ static void set_canvas(struct VP9Decoder_s *pbi, canvas_h; pic_config->canvas_config[1].block_mode = blkmode; - pic_config->canvas_config[1].endian = 7; + pic_config->canvas_config[1].endian = pbi->is_used_v4l ? 0 : 7; #endif } } @@ -6609,6 +6761,16 @@ static void set_frame_info(struct VP9Decoder_s *pbi, struct vframe_s *vf) ar = min_t(u32, pbi->frame_ar, DISP_RATIO_ASPECT_RATIO_MAX); vf->ratio_control = (ar << DISP_RATIO_ASPECT_RATIO_BIT); + if (pbi->is_used_v4l && pbi->vf_dp.present_flag) { + struct aml_vdec_hdr_infos hdr; + struct aml_vcodec_ctx *ctx = + (struct aml_vcodec_ctx *)(pbi->v4l2_ctx); + + memset(&hdr, 0, sizeof(hdr)); + hdr.signal_type = vf->signal_type; + hdr.color_parms = pbi->vf_dp; + vdec_v4l_set_hdr_infos(ctx, &hdr); + } } static int vvp9_vf_states(struct vframe_states *states, void *op_arg) @@ -6659,6 +6821,7 @@ static struct vframe_s *vvp9_vf_get(void *op_arg) uint8_t index = vf->index & 0xff; if (index < pbi->used_buf_num || (vf->type & VIDTYPE_V4L_EOS)) { + vf->index_disp = pbi->vf_get_count; pbi->vf_get_count++; if (debug & VP9_DEBUG_BUFMGR) pr_info("%s type 0x%x w/h %d/%d, pts %d, %lld\n", @@ -6684,6 +6847,9 @@ static void vvp9_vf_put(struct vframe_s *vf, void *op_arg) struct VP9Decoder_s *pbi = (struct VP9Decoder_s *)op_arg; uint8_t index = vf->index & 0xff; + if (vf == (&pbi->vframe_dummy)) + return; + kfifo_put(&pbi->newframe_q, (const struct vframe_s *)vf); pbi->vf_put_count++; if (index < pbi->used_buf_num) { @@ -6695,6 +6861,9 @@ static void vvp9_vf_put(struct vframe_s *vf, void *op_arg) if (pool->frame_bufs[index].buf.vf_ref > 0) pool->frame_bufs[index].buf.vf_ref--; + if (pbi->is_used_v4l) + pool->frame_bufs[index].buf.vframe_bound = true; + if (pbi->wait_buf) WRITE_VREG(HEVC_ASSIST_MBOX0_IRQ_REG, 0x1); @@ -6864,16 +7033,11 @@ static int prepare_display_buf(struct VP9Decoder_s *pbi, vf->v4l_mem_handle = pbi->m_BUF[pic_config->BUF_index].v4l_ref_buf_addr; if (pbi->mmu_enable) { - if (vdec_v4l_binding_fd_and_vf(vf->v4l_mem_handle, vf) < 0) { - vp9_print(pbi, PRINT_FLAG_V4L_DETAIL, - "v4l: binding vf fail.\n"); - return -1; - } + vf->mm_box.bmmu_box = pbi->bmmu_box; + vf->mm_box.bmmu_idx = HEADER_BUFFER_IDX(pic_config->BUF_index); + vf->mm_box.mmu_box = pbi->mmu_box; + vf->mm_box.mmu_idx = pic_config->index; } - vp9_print(pbi, PRINT_FLAG_V4L_DETAIL, - "[%d] %s(), v4l mem handle: 0x%lx\n", - ((struct aml_vcodec_ctx *)(pbi->v4l2_ctx))->id, - __func__, vf->v4l_mem_handle); } #ifdef MULTI_INSTANCE_SUPPORT @@ -7126,26 +7290,31 @@ static int notify_v4l_eos(struct vdec_s *vdec) { struct VP9Decoder_s *hw = (struct VP9Decoder_s *)vdec->private; struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)(hw->v4l2_ctx); - struct vframe_s *vf = NULL; + struct vframe_s *vf = &hw->vframe_dummy; struct vdec_v4l2_buffer *fb = NULL; + int index = INVALID_IDX; + ulong expires; if (hw->is_used_v4l && hw->eos) { - if (kfifo_get(&hw->newframe_q, &vf) == 0 || vf == NULL) { - vp9_print(hw, 0, - "%s fatal error, no available buffer slot.\n", - __func__); - return -1; + expires = jiffies + msecs_to_jiffies(2000); + while (INVALID_IDX == (index = v4l_get_free_fb(hw))) { + if (time_after(jiffies, expires) || + v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx)) + break; } - if (vdec_v4l_get_buffer(hw->v4l2_ctx, &fb)) { - pr_err("[%d] get fb fail.\n", ctx->id); - return -1; + if (index == INVALID_IDX) { + if (vdec_v4l_get_buffer(hw->v4l2_ctx, &fb) < 0) { + pr_err("[%d] EOS get free buff fail.\n", ctx->id); + return -1; + } } - vf->type |= VIDTYPE_V4L_EOS; - vf->timestamp = ULONG_MAX; - vf->v4l_mem_handle = (unsigned long)fb; - vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L; + vf->type |= VIDTYPE_V4L_EOS; + vf->timestamp = ULONG_MAX; + vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L; + vf->v4l_mem_handle = (index == INVALID_IDX) ? (ulong)fb : + hw->m_BUF[index].v4l_ref_buf_addr; kfifo_put(&hw->display_q, (const struct vframe_s *)vf); vf_notify_receiver(vdec->vf_provider_name, @@ -8160,15 +8329,15 @@ static irqreturn_t vvp9_isr_thread_fn(int irq, void *data) pbi->frame_width = vp9_param.p.width; pbi->frame_height = vp9_param.p.height; if (ctx->param_sets_from_ucode && !pbi->v4l_params_parsed) { - struct aml_vdec_pic_infos info; + struct aml_vdec_ps_infos ps; - info.visible_width = pbi->frame_width; - info.visible_height = pbi->frame_height; - info.coded_width = ALIGN(pbi->frame_width, 32); - info.coded_height = ALIGN(pbi->frame_height, 32); - info.dpb_size = pbi->used_buf_num; + ps.visible_width = pbi->frame_width; + ps.visible_height = pbi->frame_height; + ps.coded_width = ALIGN(pbi->frame_width, 32); + ps.coded_height = ALIGN(pbi->frame_height, 32); + ps.dpb_size = pbi->used_buf_num; pbi->v4l_params_parsed = true; - vdec_v4l_set_pic_infos(ctx, &info); + vdec_v4l_set_ps_infos(ctx, &ps); } } @@ -9648,8 +9817,13 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) if (ctx->param_sets_from_ucode && !ctx->v4l_codec_ready && - pbi->v4l_params_parsed) + pbi->v4l_params_parsed) { ret = 0; /*the params has parsed.*/ + } else if (!ctx->v4l_codec_dpb_ready) { + if (v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) < + run_ready_min_buf_num) + ret = 0; + } } if (ret) @@ -9695,6 +9869,7 @@ static void run_front(struct vdec_s *vdec) vdec_schedule_work(&pbi->work); return; } + input_empty[pbi->index] = 0; pbi->dec_result = DEC_RESULT_NONE; pbi->start_shift_bytes = READ_VREG(HEVC_SHIFT_BYTE_COUNT); @@ -9965,6 +10140,8 @@ static void init_frame_bufs(struct VP9Decoder_s *pbi) frame_bufs[i].ref_count = 0; frame_bufs[i].buf.vf_ref = 0; frame_bufs[i].buf.decode_idx = 0; + frame_bufs[i].buf.cma_alloc_addr = 0; + frame_bufs[i].buf.index = i; } if (vdec->parallel_dec == 1) { @@ -9981,7 +10158,6 @@ static void init_frame_bufs(struct VP9Decoder_s *pbi) static void reset(struct vdec_s *vdec) { - struct VP9Decoder_s *pbi = (struct VP9Decoder_s *)vdec->private; @@ -9997,7 +10173,6 @@ static void reset(struct vdec_s *vdec) } pbi->dec_result = DEC_RESULT_NONE; reset_process_time(pbi); - dealloc_mv_bufs(pbi); vp9_local_uninit(pbi); if (vvp9_local_init(pbi) < 0) vp9_print(pbi, 0, "%s local_init failed \r\n", __func__); @@ -10286,6 +10461,21 @@ static int ammvdec_vp9_probe(struct platform_device *pdev) pbi->max_pic_h = vp9_buf_height; vp9_print(pbi, 0, "use buf resolution\n"); } + + if (get_config_int(pdata->config, + "parm_v4l_codec_enable", + &config_val) == 0) + pbi->is_used_v4l = config_val; + + if (get_config_int(pdata->config, + "parm_v4l_buffer_margin", + &config_val) == 0) + pbi->dynamic_buf_num_margin = config_val; + + if (get_config_int(pdata->config, + "parm_v4l_canvas_mem_mode", + &config_val) == 0) + pbi->mem_map_mode = config_val; #endif if (get_config_int(pdata->config, "HDRStaticInfo", &vf_dp.present_flag) == 0 @@ -10333,6 +10523,11 @@ static int ammvdec_vp9_probe(struct platform_device *pdev) pbi->vvp9_amstream_dec_info.rate = 30;*/ pbi->double_write_mode = double_write_mode; } + + if (!pbi->is_used_v4l) { + pbi->mem_map_mode = mem_map_mode; + } + if (is_oversize(pbi->max_pic_w, pbi->max_pic_h)) { pr_err("over size: %dx%d, probe failed\n", pbi->max_pic_w, pbi->max_pic_h); @@ -10349,18 +10544,6 @@ static int ammvdec_vp9_probe(struct platform_device *pdev) pbi->vvp9_amstream_dec_info.rate = 30; } pbi->low_latency_flag = 1; - pbi->is_used_v4l = (((unsigned long) - pbi->vvp9_amstream_dec_info.param & 0x80) >> 7); - if (pbi->is_used_v4l) { - pbi->mmu_enable = (((unsigned long) - pbi->vvp9_amstream_dec_info.param & 0x100) >> 8); - if (!pbi->mmu_enable) - pbi->double_write_mode = 0x10; - - pbi->mmu_enable = 1; - pbi->max_pic_w = 4096; - pbi->max_pic_h = 2304; - } vp9_print(pbi, 0, "no_head %d low_latency %d\n", diff --git a/drivers/frame_sink/encoder/h264/encoder.c b/drivers/frame_sink/encoder/h264/encoder.c index 7b83dd2..294c600 100644 --- a/drivers/frame_sink/encoder/h264/encoder.c +++ b/drivers/frame_sink/encoder/h264/encoder.c @@ -1067,6 +1067,8 @@ static int scale_frame(struct encode_wq_s *wq, src_left = request->crop_left; src_width = request->src_w - src_left - request->crop_right; src_height = request->src_h - src_top - request->crop_bottom; + pr_err("request->fmt=%d, %d %d, canvas=%d\n", request->fmt, FMT_NV21, FMT_BGR888, canvas); + if (canvas) { if ((request->fmt == FMT_NV21) || (request->fmt == FMT_NV12)) { @@ -1075,6 +1077,9 @@ static int scale_frame(struct encode_wq_s *wq, } else if (request->fmt == FMT_BGR888) { src_canvas = src_addr & 0xffffff; input_format = GE2D_FORMAT_S24_RGB; //Opposite color after ge2d + } else if (request->fmt == FMT_RGBA8888) { + src_canvas = src_addr & 0xffffff; + input_format = GE2D_FORMAT_S32_ABGR; } else { src_canvas = src_addr & 0xffffff; input_format = GE2D_FORMAT_M24_YUV420; @@ -1101,6 +1106,7 @@ static int scale_frame(struct encode_wq_s *wq, } else if (request->fmt == FMT_BGR888) { src_canvas_w = ((request->src_w + 31) >> 5) << 5; + canvas_config(ENC_CANVAS_OFFSET + 9, src_addr, src_canvas_w * 3, src_h, @@ -1108,6 +1114,18 @@ static int scale_frame(struct encode_wq_s *wq, CANVAS_BLKMODE_LINEAR); src_canvas = ENC_CANVAS_OFFSET + 9; input_format = GE2D_FORMAT_S24_RGB; //Opposite color after ge2d + } else if (request->fmt == FMT_RGBA8888) { + src_canvas_w = + ((request->src_w + 31) >> 5) << 5; + canvas_config( + ENC_CANVAS_OFFSET + 9, + src_addr, + src_canvas_w * 4, + src_h, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + src_canvas = ENC_CANVAS_OFFSET + 9; + input_format = GE2D_FORMAT_S32_ABGR; //Opposite color after ge2d } else { src_canvas_w = ((request->src_w + 63) >> 6) << 6; @@ -1133,17 +1151,22 @@ static int scale_frame(struct encode_wq_s *wq, input_format = GE2D_FORMAT_M24_YUV420; } } + dst_canvas_w = ((dst_w + 31) >> 5) << 5; + canvas_config(ENC_CANVAS_OFFSET + 6, wq->mem.scaler_buff_start_addr, dst_canvas_w, dst_h, CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); + canvas_config(ENC_CANVAS_OFFSET + 7, wq->mem.scaler_buff_start_addr + dst_canvas_w * dst_h, dst_canvas_w, dst_h / 2, CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); + dst_canvas = ((ENC_CANVAS_OFFSET + 7) << 8) | (ENC_CANVAS_OFFSET + 6); + ge2d_config->alu_const_color = 0; ge2d_config->bitmask_en = 0; ge2d_config->src1_gb_alpha = 0; @@ -1152,18 +1175,20 @@ static int scale_frame(struct encode_wq_s *wq, canvas_read((src_canvas >> 8) & 0xff, &cs1); canvas_read((src_canvas >> 16) & 0xff, &cs2); ge2d_config->src_planes[0].addr = cs0.addr; - ge2d_config->src_planes[0].w = cs0.width; - ge2d_config->src_planes[0].h = cs0.height; + ge2d_config->src_planes[0].w = dst_w * 4;//cs0.width; + ge2d_config->src_planes[0].h = dst_h;//cs0.height; ge2d_config->src_planes[1].addr = cs1.addr; ge2d_config->src_planes[1].w = cs1.width; ge2d_config->src_planes[1].h = cs1.height; ge2d_config->src_planes[2].addr = cs2.addr; ge2d_config->src_planes[2].w = cs2.width; ge2d_config->src_planes[2].h = cs2.height; + canvas_read(dst_canvas & 0xff, &cd); + ge2d_config->dst_planes[0].addr = cd.addr; - ge2d_config->dst_planes[0].w = cd.width; - ge2d_config->dst_planes[0].h = cd.height; + ge2d_config->dst_planes[0].w = dst_w * 4;//cd.width; + ge2d_config->dst_planes[0].h = dst_h;//cd.height; ge2d_config->src_key.key_enable = 0; ge2d_config->src_key.key_mask = 0; ge2d_config->src_key.key_mode = 0; @@ -1177,13 +1202,18 @@ static int scale_frame(struct encode_wq_s *wq, ge2d_config->src_para.color = 0xffffffff; ge2d_config->src_para.top = 0; ge2d_config->src_para.left = 0; - ge2d_config->src_para.width = request->src_w; - ge2d_config->src_para.height = request->src_h; + ge2d_config->src_para.width = dst_w;//request->src_w; + ge2d_config->src_para.height = dst_h;//request->src_h; ge2d_config->src2_para.mem_type = CANVAS_TYPE_INVALID; ge2d_config->dst_para.canvas_index = dst_canvas; ge2d_config->dst_para.mem_type = CANVAS_TYPE_INVALID; ge2d_config->dst_para.format = GE2D_FORMAT_M24_NV21 | GE2D_LITTLE_ENDIAN; + + if (wq->pic.encoder_width >= 1280 && wq->pic.encoder_height >= 720) { + ge2d_config->dst_para.format |= GE2D_FORMAT_BT_STANDARD; + } + ge2d_config->dst_para.fill_color_en = 0; ge2d_config->dst_para.fill_mode = 0; ge2d_config->dst_para.x_rev = 0; @@ -1196,6 +1226,7 @@ static int scale_frame(struct encode_wq_s *wq, ge2d_config->dst_para.x_rev = 0; ge2d_config->dst_para.y_rev = 0; + if (ge2d_context_config_ex(context, ge2d_config) < 0) { pr_err("++ge2d configing error.\n"); return -1; @@ -1225,6 +1256,7 @@ static s32 set_input_format(struct encode_wq_s *wq, picsize_x = ((wq->pic.encoder_width + 15) >> 4) << 4; picsize_y = ((wq->pic.encoder_height + 15) >> 4) << 4; oformat = 0; + if ((request->type == LOCAL_BUFF) || (request->type == PHYSICAL_BUFF) || (request->type == DMA_BUFF)) { @@ -2670,6 +2702,19 @@ static s32 convert_request(struct encode_wq_s *wq, u32 *cmd_info) wq->request.src_w = cmd_info[13]; wq->request.src_h = cmd_info[14]; wq->request.scale_enable = cmd_info[15]; + + enc_pr(LOG_INFO, "hwenc: wq->pic.encoder_width %d, ", + wq->pic.encoder_width); + enc_pr(LOG_INFO, "wq->pic.encoder_height:%d, request fmt=%d\n", + wq->pic.encoder_height, wq->request.fmt); + + if (wq->pic.encoder_width >= 1280 && wq->pic.encoder_height >= 720 && wq->request.fmt == FMT_RGBA8888) { + wq->request.scale_enable = 1; + wq->request.src_w = wq->pic.encoder_width; + wq->request.src_h = wq->pic.encoder_height; + pr_err("hwenc: force wq->request.scale_enable=%d\n", wq->request.scale_enable); + } + wq->request.nr_mode = (nr_mode > 0) ? nr_mode : cmd_info[16]; if (cmd == ENCODER_IDR) @@ -3216,6 +3261,7 @@ static long amvenc_avc_ioctl(struct file *file, u32 cmd, ulong arg) wq->mem.bufspec.max_height, (void *)wq); return -1; } + pr_err("hwenc: AMVENC_AVC_IOC_CONFIG_INIT: w:%d, h:%d\n", wq->pic.encoder_width, wq->pic.encoder_height); wq->pic.encoder_width = addr_info[2]; wq->pic.encoder_height = addr_info[3]; if (wq->pic.encoder_width * diff --git a/drivers/stream_input/parser/hw_demux/aml_dmx.c b/drivers/stream_input/parser/hw_demux/aml_dmx.c index 286b922..52334da 100644 --- a/drivers/stream_input/parser/hw_demux/aml_dmx.c +++ b/drivers/stream_input/parser/hw_demux/aml_dmx.c @@ -129,6 +129,9 @@ module_param_array(debug_dmx##_dmx##_chanpids, short, &npids, 0444) #define CIPLUS_OUTPUT_AUTO 8 static int ciplus_out_sel = CIPLUS_OUTPUT_AUTO; static int ciplus_out_auto_mode = 1; +static u32 ciplus = 0; +#define CIPLUS_OUT_SEL 28 +#define CIPLUS_IN_SEL 26 MOD_PARAM_DECLARE_CHANPIDS(0); MOD_PARAM_DECLARE_CHANPIDS(1); @@ -1615,7 +1618,6 @@ static void stb_enable(struct aml_dvb *dvb) dec_clk_en = 0; break; } - switch (dvb->tso_source) { case AM_TS_SRC_DMX0: tso_src = dvb->dmx[0].source; @@ -1690,8 +1692,9 @@ static void stb_enable(struct aml_dvb *dvb) (en_des << ENABLE_DES_PL) | (dec_clk_en << ENABLE_DES_PL_CLK) | (invert0 << INVERT_S2P0_FEC_CLK) | - (fec_s0 << S2P0_FEC_SERIAL_SEL)); - + (fec_s0 << S2P0_FEC_SERIAL_SEL)| + (ciplus)); + ciplus = 0; if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TL1) { invert2 = dvb->s2p[2].invert; @@ -1761,6 +1764,25 @@ int dsc_set_pid(struct aml_dsc_channel *ch, int pid) return 0; } +int dsc_get_pid(struct aml_dsc_channel *ch, int *pid) +{ + struct aml_dsc *dsc = ch->dsc; + int is_dsc2 = (dsc->id == 1) ? 1 : 0; + u32 data; + + WRITE_MPEG_REG(TS_PL_PID_INDEX, + ((ch->id & 0x0f) >> 1)+(is_dsc2 ? 4 : 0)); + data = READ_MPEG_REG(TS_PL_PID_DATA); + if (ch->id & 1) { + *pid = data & 0x1fff; + } else { + *pid = (data >> 16) & 0x1fff; + } + + /*pr_dbg("%s,get DSC %d ch %d PID %d\n", __FUNCTION__,dsc->id, ch->id, *pid);*/ + return 0; +} + int dsc_set_key(struct aml_dsc_channel *ch, int flags, enum ca_cw_type type, u8 *key) { @@ -1931,8 +1953,6 @@ static int dsc_set_csa_key(struct aml_dsc_channel *ch, int flags, #define ENABLE_DEC_PL 7 #define ENABLE_DES_PL_CLK 15 -#define CIPLUS_OUT_SEL 28 -#define CIPLUS_IN_SEL 26 #define KEY_WR_AES_IV_B 5 #define KEY_WR_AES_IV_A 4 @@ -3273,9 +3293,12 @@ static u32 dmx_get_chan_target(struct aml_dmx *dmx, int cid) case DMX_PES_PCR: type = SCR_ONLY_PACKET; break; - default: + case DMX_PES_AUDIO3: type = OTHER_PES_PACKET; break; + default: + type = BYPASS_PACKET; + break; } } @@ -3726,8 +3749,22 @@ void dmx_reset_hw_ex(struct aml_dvb *dvb, int reset_irq) if (reset_irq) del_timer_sync(&dvb->watchdog_timer); #endif + /*RESET_TOP will clear the dsc pid , save all dsc pid that setting in TA*/ + for (id = 0; id < DSC_DEV_COUNT; id++) { + struct aml_dsc *dsc = &dvb->dsc[id]; + int n; - WRITE_MPEG_REG(RESET1_REGISTER, RESET_DEMUXSTB); + for (n = 0; n < DSC_COUNT; n++) { + struct aml_dsc_channel *ch = &dsc->channel[n]; + /*if(ch->used)*/ + { + ch->id = n; + dsc_get_pid(ch,&ch->pid); + } + } + } + /*WRITE_MPEG_REG(RESET1_REGISTER, RESET_DEMUXSTB);*/ + WRITE_MPEG_REG(RESET3_REGISTER, RESET_DEMUX2|RESET_DEMUX1|RESET_DEMUX0|RESET_S2P1|RESET_S2P0|RESET_TOP); for (id = 0; id < DMX_DEV_COUNT; id++) { times = 0; @@ -3736,6 +3773,11 @@ void dmx_reset_hw_ex(struct aml_dvb *dvb, int reset_irq) break; } } + { + u32 data; + data = READ_MPEG_REG(STB_TOP_CONFIG); + ciplus = 0xF8000000 & data; + } WRITE_MPEG_REG(STB_TOP_CONFIG, 0); WRITE_MPEG_REG(STB_S2P2_CONFIG, 0); @@ -3859,13 +3901,20 @@ void dmx_reset_hw_ex(struct aml_dvb *dvb, int reset_irq) int n; for (n = 0; n < DSC_COUNT; n++) { + int flag = 0; struct aml_dsc_channel *ch = &dsc->channel[n]; - /*if(ch->used) */ + /*if(ch->used)*/ { - ch->id = n; ch->work_mode = -1; + //if ta setting pid, used will 0 + if (ch->pid != 0x1fff && !ch->used) { + flag = 1; + ch->used = 1; + } dsc_set_pid(ch, ch->pid); - dsc_set_keys(ch); + if (flag) + ch->used = 0; + //dsc_set_keys(ch); } } } @@ -3917,6 +3966,11 @@ void dmx_reset_dmx_hw_ex_unlock(struct aml_dvb *dvb, struct aml_dmx *dmx, } /*WRITE_MPEG_REG(STB_TOP_CONFIG, 0); */ + { + u32 data; + data = READ_MPEG_REG(STB_TOP_CONFIG); + ciplus = 0xF8000000 & data; + } { u32 version, data; @@ -4045,11 +4099,21 @@ void dmx_reset_dmx_hw_ex_unlock(struct aml_dvb *dvb, struct aml_dmx *dmx, int n; for (n = 0; n < DSC_COUNT; n++) { + int flag = 0; struct aml_dsc_channel *ch = &dsc->channel[n]; - /*if(ch->used) */ + /*if(ch->used)*/ { + ch->id = n; ch->work_mode = -1; + dsc_get_pid(ch,&ch->pid); + if (ch->pid != 0x1fff && !ch->used) { + flag = 1; + ch->used = 1; + } dsc_set_pid(ch, ch->pid); - dsc_set_keys(ch); + if (flag) + ch->used = 0; + //dsc_set_keys(ch); + } } } } @@ -4152,6 +4216,7 @@ int dmx_alloc_chan(struct aml_dmx *dmx, int type, int pes_type, int pid) id = 3; break; case DMX_PES_OTHER: + case DMX_PES_AUDIO3: { int i; diff --git a/firmware/video_ucode.bin b/firmware/video_ucode.bin index 6ef6866..cf1c3b9 100644 --- a/firmware/video_ucode.bin +++ b/firmware/video_ucode.bin @@ -1,5 +1,5 @@ -*wSж!whs9+Π7"*.:k.-.ipj1
9No3y5DF_GOi8T }T{ȏ^"Ōҝ7#SKqSA<~u -j T4sƨ({V08a>5kxtΛŸnŁأ~ۮ0_5`3@Ï04P"##LdWKCAP +ejBe=4&8+ߘTtWGIߴ$Ym IoA1aŋEױv +5qa8џ3kY{s40-am2l@?BgX R,h=~H\&ɕ.Rc(vd-\\uq՟I`|TVwFAT!Hȷ~<W4+~JnKCAP @ I` @@ -392,7 +392,7 @@ j 2 ! , x3 - + @ I` =y` @@ -845,7 +845,7 @@ j 2 ! , x3 - + @ I` @@ -1237,7 +1237,7 @@ j 2 ! , x3 - + @ I` @@ -1629,7 +1629,7 @@ j 2 ! , x3 - + @ I` @@ -2016,7 +2016,7 @@ j 2 ! , x3 - + @ I` @@ -2409,7 +2409,7 @@ j 2 ! , x3 - + @x Ȁ @@ -2423,7 +2423,7 @@ H H @p 6
-@ +@ % x @@ -2434,7 +2434,7 @@ H H x -@ +@ @ I` x` @@ -2923,7 +2923,7 @@ HCP
HCX
"@Ir C C @ Ir C C 3 -C C B LCH +C C B LCH @ I` x` @@ -3411,7 +3411,7 @@ HCP
HCX
"@Ir C C @ Ir C C 3 -C C B LCH +C C B LCH @ I` x` @@ -3899,7 +3899,7 @@ HCP
HCX
"@Ir C C @ Ir C C 3 -C C B LCH +C C B LCH @ I` x` @@ -4387,7 +4387,7 @@ HCP
HCX
"@Ir C C @ Ir C C 3 -C C B LCH +C C B LCH @ I` x` @@ -4875,7 +4875,7 @@ HCP
HCX
"@Ir C C @ Ir C C 3 -C C B LCH +C C B LCH I v G @@ -4968,7 +4968,7 @@ U T%H @ID T%H @ID T%H @ID -U +U I@ v G @@ -5070,7 +5070,7 @@ U T%H @ID T%H @ID T%H @ID -U +U I v @@ -5165,7 +5165,7 @@ U T%H @ID T%H @ID T%H @ID -U +U I@ v @@ -5269,14 +5269,14 @@ U T%H @ID T%H @ID T%H @ID -U +U - + x B< @@ -5833,7 +5833,7 @@ I G @@?# -G"@ ;#@= +G"@ ;#@= x B< @@ -6378,7 +6378,7 @@ I G @ -G"@ @<#= +G"@ @<#= x B< @@ -6936,7 +6936,7 @@ I G @@?# G"@ ;#@= -gxm_h264_multi.bin +gxm_h264_multi.bin x B< @@ -7483,11 +7483,11 @@ I G @ -G"@ @<#= +G"@ @<#= -tl1_h264_multi.bin +tl1_h264_multi.bin x B< @@ -8034,7 +8034,7 @@ I G @ -G"@ @<#= +G"@ @<#= I ! `xI@ C @ @@ -8432,7 +8432,7 @@ EG EŅ " EG ņ -EŇ " +EŇ " I ! `xI@ C @ @@ -8830,7 +8830,7 @@ EG EŅ " EG ņ -EŇ " +EŇ " I ! `xI@ C @ @@ -9202,7 +9202,7 @@ EŇ@x EG ł EŃ@ -` +` I ! `xI@ C @ @@ -9574,7 +9574,7 @@ EŇ@x EG ł EŃ@ -` +` I ! `xI@ C @ @@ -9972,7 +9972,7 @@ EG EŅ " EG ņ -EŇ " +EŇ " I ! `iI@ C @ @@ -10344,7 +10344,7 @@ EŇ@x EG ł EŃ@ -` +` I ! `xI@ C @ @@ -10716,7 +10716,7 @@ EŇ@x EG ł EŃ@ -` +` I ! `iI@ C @ @@ -11114,7 +11114,7 @@ EG EŅ " EG ņ -EŇ " +EŇ " I ! `xI@ C @ @@ -11486,7 +11486,7 @@ EŇ@x EG ł EŃ@ -` +` I ! `xI@ C @ @@ -11884,7 +11884,7 @@ EG EŅ " EG ņ -EŇ " +EŇ " @4x @@ -12065,7 +12065,7 @@ n J` -J` +J` @@ -12263,7 +12263,7 @@ n J` -J` +J` @@ -12276,25 +12276,25 @@ n - + y o c HCc -I +I x *L6Lǁ Q ;LH2 H L ` -@@I +@@I x @x -2 +2 (GGCG @@ -12312,7 +12312,7 @@ x ` X ȃ -, +, q@BD HH@d @@ -12331,13 +12331,13 @@ HA @ " N"HD 2P @x!xA! - +@ `@ ` - - + + Hzo N @@ -12394,7 +12394,7 @@ G GG -B + @@ -12450,7 +12450,7 @@ J xGGP !@$N @ " -N"HD 2P @x!xA! +N"HD 2P @x!xA! GG G G` @@ -12475,10 +12475,10 @@ I "B @x@@ o @ -ۆ[@GLa~ ǀ +ۆ[@GLa~ ׀ - - + +@e ( ! (@( hQ @@ -12489,7 +12489,7 @@ kè +B * -* +* ! ( 銂( ( @@ -12546,11 +12546,11 @@ G NNN - -@ + +@ ! G - + ߏN Lȃ JB ` @@ -12559,7 +12559,7 @@ G *C(I( ,J@($,*F ( ) ("L(h! ( 튂( ( ,J@ ($("Lh! ( 튂( , -("Lh! ( 튂( +("Lh! ( 튂( @@ -12572,25 +12572,25 @@ G - + @y o c HCc -I +I x *L6Lǁ Q ;LH2 H L ` -@@I +@@I x @x -2 +2 (GGCG @@ -12608,7 +12608,7 @@ x ` X ȃ -, +, q@BD HH@d @@ -12627,13 +12627,13 @@ HA @ " N"HD 2P @x!xA! - +@ `@ ` - - + + Hzo N @@ -12690,7 +12690,7 @@ G GG -B + @@ -12747,7 +12747,7 @@ J xGGP !@$N @ " -N"HD 2P @x!xA! +N"HD 2P @x!xA! GG G G` @@ -12772,10 +12772,10 @@ I "B @x@@ o @ -ۆ[@GLa~ ǀ +ۆ[@GLa~ ׀ - - + +@e ( ! (@( hQ @@ -12786,7 +12786,7 @@ kè +B * -* +* ! ( 銂( ( @@ -12843,11 +12843,11 @@ G NNN - -@ + +@ ! G - + ߏN Lȃ JB ` @@ -12856,7 +12856,7 @@ G *C(I( ,J@($,*F ( ) ("L(h! ( 튂( ( ,J@ ($("Lh! ( 튂( , -("Lh! ( 튂( +("Lh! ( 튂( @@ -12869,25 +12869,25 @@ G - + @y o c HCc -I +I x *L6Lǁ Q ;LH2 H L ` -@@I +@@I x @x -2 +2 (GGCG @@ -12905,7 +12905,7 @@ x ` X ȃ -, +, q@BD HH@d @@ -12924,13 +12924,13 @@ HA @ " N"HD 2P @x!xA! - +@ `@ ` - - + + Hzo N @@ -12987,7 +12987,7 @@ G GG -B + @@ -13044,7 +13044,7 @@ J xGGP !@$N @ " -N"HD 2P @x!xA! +N"HD 2P @x!xA! GG G G` @@ -13069,10 +13069,10 @@ I "B @x@@ o @ -ۆ[@GLa~ ǀ +ۆ[@GLa~ ׀ - - + +@e ( ! (@( hQ @@ -13083,7 +13083,7 @@ kè +B * -* +* ! ( 銂( ( @@ -13140,11 +13140,11 @@ G NNN - -@ + +@ ! G - + ߏN Lȃ JB ` @@ -13153,7 +13153,7 @@ G *C(I( ,J@($,*F ( ) ("L(h! ( 튂( ( ,J@ ($("Lh! ( 튂( , -("Lh! ( 튂( +("Lh! ( 튂( @@ -13166,25 +13166,25 @@ G - + y o c HCc -I +I x *L6Lǁ Q ;LH2 H L ` -@@I +@@I x @x -2 +2 (GGCG @@ -13202,7 +13202,7 @@ x ` X ȃ -, +, q@BD HH@d @@ -13221,13 +13221,13 @@ HA @ " N"HD 2P @x!xA! - +@ `@ ` - - + + Hzo N @@ -13284,7 +13284,7 @@ G GG -B + @@ -13340,7 +13340,7 @@ J xGGP !@$N @ " -N"HD 2P @x!xA! +N"HD 2P @x!xA! GG G G` @@ -13365,10 +13365,10 @@ I "B @x@@ o @ -ۆ[@GLa~ ǀ +ۆ[@GLa~ ׀ - - + +@e ( ! (@( hQ @@ -13379,7 +13379,7 @@ kè +B * -* +* ! ( 銂( ( @@ -13436,11 +13436,11 @@ G NNN - -@ + +@ ! G - + ߏN Lȃ JB ` @@ -13449,7 +13449,7 @@ G *C(I( ,J@($,*F ( ) ("L(h! ( 튂( ( ,J@ ($("Lh! ( 튂( , -("Lh! ( 튂( +("Lh! ( 튂( @@ -13635,26 +13635,26 @@ D@ @ @xHR& b@I"@J@Hb - + - + - + -:x +:x G
@a @x - + , - + -@ +@ ! @@ -13667,46 +13667,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@Z - +k@W@[ + r -H - +H + @I ` G
` -@x +@x G`HR@ `"@ - - + + b 2x -B +B - + A @a - + @@ -13716,7 +13716,7 @@ G
` @I ^ G \ G Z -I +I @@ -13729,40 +13729,41 @@ QRIc P PCIIG
B G LI B HbBx a t - + -` +a GIǁ a O I@I - + -@ x +@ x > @x - + xQL FLBL -@Lr@ǁ +@Lr@ǁ ?I H I HR I Ix I I L H2X - IH - + IH + + - + @@ -13781,7 +13782,7 @@ H2X I A@_` -T@GL~ +T@GL~ U @@ -13822,7 +13823,7 @@ D@ @ @xHR& b@I"@J@Hb - + @@ -14008,26 +14009,26 @@ D@ @ @xHR& b@I"@J@Hb - + - + - + -:x +:x G
@a @x - + , - + -@ +@ ! @@ -14040,46 +14041,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@Z - +k@W@[ + r -H - +H + @I ` G
` -@x +@x G`HR@ `"@ - - + + b 2x -B +B - + A @a - + @@ -14089,7 +14090,7 @@ G
` @I ^ G \ G Z -I +I @@ -14102,40 +14103,41 @@ QRIc P PCIIG
B G LI B HbBx a t - + -` +a GIǁ a O I@I - + -@ x +@ x > @x - + xQL FLBL -@Lr@ǁ +@Lr@ǁ ?I H I HR I Ix I I L H2X - IH - + IH + + - + @@ -14154,7 +14156,7 @@ H2X I A@_` -T@GL~ +T@GL~ U @@ -14195,7 +14197,8 @@ D@ @ @xHR& b@I"@J@Hb - + +]I6d127c5 y G@, % @@ -14513,7 +14516,7 @@ G *C(I( ,J@($,*F ( ) ("L(h! ( 튂( ( ,J@ ($("Lh! ( 튂( , -("Lh! ( 튂( +("Lh! ( 튂( G+ % @@ -14805,7 +14808,7 @@ G @ ! G - + G+ % @@ -15097,7 +15100,8 @@ G @ ! G - + +]I6d127c5 G+ % @@ -15389,7 +15393,8 @@ G @ ! G - + +]I6d127c5 y G@, % @@ -15707,7 +15712,7 @@ G *C(I( ,J@($,*F ( ) ("L(h! ( 튂( ( ,J@ ($("Lh! ( 튂( , -("Lh! ( 튂( +("Lh! ( 튂( y G@, % @@ -16025,7 +16030,7 @@ G *C(I( ,J@($,*F ( ) ("L(h! ( 튂( ( ,J@ ($("Lh! ( 튂( , -("Lh! ( 튂( +("Lh! ( 튂( y G@, % @@ -16343,7 +16348,8 @@ G *C(I( ,J@($,*F ( ) ("L(h! ( 튂( ( ,J@ ($("Lh! ( 튂( , -("Lh! ( 튂( +("Lh! ( 튂( +]I6d127c5 G+ % @@ -16635,7 +16641,8 @@ G @ ! G - + +]I6d127c5 x ` x @@ -16850,7 +16857,8 @@ E - + +]I6d127c5 x ` x @@ -17065,7 +17073,8 @@ E - + +]I6d127c5 x ` x @@ -17287,7 +17296,8 @@ E - + +]I6d127c5 @ I` @x` @@ -17666,7 +17676,8 @@ H *AL+CLh j@ j - + +]I6d127c5 @ I` @@ -18045,7 +18056,8 @@ H *AL+CLh j@ j - + +]I6d127c5 @ I` @x` @@ -18424,7 +18436,8 @@ H *AL+CLh j@ j - + +]I6d127c5 @ I` @@ -18862,7 +18875,8 @@ H *AL+CLh j@ j - + +]I6d127c5 @ I` @x` @@ -19235,7 +19249,8 @@ H *AL+CLh j@ j - + +]I6d127c5 @ I` @@ -19614,7 +19629,8 @@ H *AL+CLh j@ j - + +]I6d127c5 3 @@ -20444,7 +20460,8 @@ q @ i - + +]I6d127c5 3 @@ -21275,7 +21292,7 @@ q @ i - + @` @@ -21924,7 +21941,7 @@ J2x 0 ` - + @` @@ -22573,7 +22590,7 @@ J2x 0 ` - + @` @@ -23222,7 +23239,7 @@ J2x 0 ` - + @` @@ -23871,7 +23888,8 @@ J2x 0 ` - + +]I6d127c5 @x @` @x @@ -24518,7 +24536,7 @@ J2x 0 ` - + x @x @@ -25047,7 +25065,7 @@ H#` & -C +C x x @@ -25586,7 +25604,7 @@ H#` & -@ +@ @ x @@ -26113,7 +26131,7 @@ H#` & -@ +@ x x @@ -26639,7 +26657,7 @@ H#` & -C +C x @x @@ -27168,7 +27186,7 @@ H#` & -C +C x @x @@ -27697,7 +27715,7 @@ H#` & -C +C x @x @@ -28226,7 +28244,7 @@ H#` & -C +C y @@ -28841,7 +28859,7 @@ H - + +@+@ @@ -29165,7 +29183,7 @@ a .
AB+@+@ -J` JJ` +J` JJ` +@+@ @@ -29487,7 +29505,7 @@ a .
AB+@+@ -J` JJ` +J` JJ` +@+@ @@ -29806,7 +29824,7 @@ a .
AB+@+@ -J` JJ` +J` JJ` +@+@ @@ -30125,7 +30143,7 @@ a .
AB+@+@ -J` JJ` +J` JJ` +@+@ @@ -30447,7 +30465,7 @@ a .
AB+@+@ -J` JJ` +J` JJ` +@+@ @@ -30772,7 +30790,7 @@ a .
AB+@+@ -J` JJ` +J` JJ` +@+@ @@ -31091,7 +31109,7 @@ a .
AB+@+@ -J` JJ` +J` JJ` FL CL R@ I` x` @@ -31319,7 +31337,7 @@ E=== E DL>L D@ @ -xHR& b@I"@J@Hb +xHR& b@I"@J@Hb FL CL R@ I` x` @@ -31545,7 +31563,7 @@ E=== E DL>L D@ @ -xHR& b@I"@J@Hb +xHR& b@I"@J@Hb FL CL R@ I` x` @@ -31773,7 +31791,7 @@ E=== E DL>L D@ @ -xHR& b@I"@J@Hb +xHR& b@I"@J@Hb FL CL R@ I` x` |