diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_adapt.c b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_adapt.c index 8b67fb6b6ec2..2f8fc822d147 100644 --- a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_adapt.c +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_adapt.c @@ -89,31 +89,17 @@ static struct stream_buf_s bufs[BUF_MAX_NUM] = { }, }; -struct vdec_adapt_config { - struct vdec_s *vdec; - struct stream_port_s port; - struct dec_sysinfo dec_prop; -}; - -struct vdec_adapt_config g_cfg; - static void set_cfg_info(struct aml_vdec_adapt *vdec) { unsigned long sync_mode = (PTS_OUTSIDE | SYNC_OUTSIDE | USE_V4L_PORTS); - g_cfg.port.type |= (PORT_TYPE_VIDEO | PORT_TYPE_ES); - g_cfg.port.flag |= PORT_FLAG_VFORMAT; - g_cfg.dec_prop.format = VFORMAT_H264; - g_cfg.dec_prop.width = 1920; - g_cfg.dec_prop.height = 1080; - g_cfg.dec_prop.rate = 3200; - g_cfg.dec_prop.param = (void *)sync_mode; -} - -static void set_system_info(struct vdec_s *vdec) -{ - vdec->sys_info = &g_cfg.dec_prop; - vdec->sys_info_store = g_cfg.dec_prop; + vdec->port.type |= (PORT_TYPE_VIDEO | PORT_TYPE_FRAME/* | PORT_TYPE_ES*/); + vdec->port.flag |= PORT_FLAG_VFORMAT; + vdec->dec_prop.format = vdec->format; + vdec->dec_prop.width = 1920; + vdec->dec_prop.height = 1080; + vdec->dec_prop.rate = 3200; + vdec->dec_prop.param = (void *)sync_mode; } static void set_vdec_mode(struct vdec_s *vdec) @@ -127,10 +113,8 @@ static void set_vdec_vfm(struct vdec_s *vdec) vdec->frame_base_video_path = FRAME_BASE_PATH_V4L_VIDEO; } -static int enable_hardware(void) +static int enable_hardware(struct stream_port_s *port) { - struct stream_port_s *port = &g_cfg.port; - if (get_cpu_type() < MESON_CPU_MAJOR_ID_M6) return -1; @@ -142,30 +126,22 @@ static int enable_hardware(void) amports_switch_gate("vdec", 1); if (has_hevc_vdec()) { - if (port->type & (PORT_TYPE_MPTS | PORT_TYPE_HEVC)) { - amports_switch_gate("clk_hevc_mux", 1); + if (port->type & (PORT_TYPE_MPTS | PORT_TYPE_HEVC)) vdec_poweron(VDEC_HEVC); - } - if ((port->type & PORT_TYPE_HEVC) == 0) { - amports_switch_gate("clk_vdec_mux", 1); + if ((port->type & PORT_TYPE_HEVC) == 0) vdec_poweron(VDEC_1); - } } else { - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) { - amports_switch_gate("clk_vdec_mux", 1); + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) vdec_poweron(VDEC_1); - } } } return 0; } -static int disable_hardware(void) +static int disable_hardware(struct stream_port_s *port) { - struct stream_port_s *port = &g_cfg.port; - if (get_cpu_type() < MESON_CPU_MAJOR_ID_M6) return -1; @@ -316,9 +292,9 @@ static int audio_component_init(struct stream_port_s *port, static void video_component_release(struct stream_port_s *port, struct stream_buf_s *pbuf, int release_num) { - struct vdec_adapt_config *cfg - = container_of(port, struct vdec_adapt_config, port); - struct vdec_s *vdec = cfg->vdec; + struct aml_vdec_adapt *ada_ctx + = container_of(port, struct aml_vdec_adapt, port); + struct vdec_s *vdec = ada_ctx->vdec; struct vdec_s *slave = NULL; bool is_multidec = !vdec_single(vdec); @@ -355,9 +331,9 @@ static int video_component_init(struct stream_port_s *port, struct stream_buf_s *pbuf) { int ret = -1; - struct vdec_adapt_config *cfg - = container_of(port, struct vdec_adapt_config, port); - struct vdec_s *vdec = cfg->vdec; + struct aml_vdec_adapt *ada_ctx + = container_of(port, struct aml_vdec_adapt, port); + struct vdec_s *vdec = ada_ctx->vdec; if ((vdec->port_flag & PORT_FLAG_VFORMAT) == 0) { pr_err("vformat not set\n"); @@ -437,9 +413,9 @@ static int video_component_init(struct stream_port_s *port, static int vdec_ports_release(struct stream_port_s *port) { - struct vdec_adapt_config *cfg - = container_of(port, struct vdec_adapt_config, port); - struct vdec_s *vdec = cfg->vdec; + struct aml_vdec_adapt *ada_ctx + = container_of(port, struct aml_vdec_adapt, port); + struct vdec_s *vdec = ada_ctx->vdec; struct stream_buf_s *pvbuf = &bufs[BUF_TYPE_VIDEO]; struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO]; @@ -492,7 +468,7 @@ static int vdec_ports_init(struct aml_vdec_adapt *vdec_adapt) struct stream_buf_s *pvbuf = &bufs[BUF_TYPE_VIDEO]; struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO]; //struct stream_buf_s *psbuf = &bufs[BUF_TYPE_SUBTITLE]; - struct stream_port_s *port = &g_cfg.port; + struct stream_port_s *port = &vdec_adapt->port; struct vdec_s *vdec = NULL; /* create the vdec instance.*/ @@ -503,11 +479,13 @@ static int vdec_ports_init(struct aml_vdec_adapt *vdec_adapt) /* set v4l2 ctx */ vdec->private = vdec_adapt->ctx; - g_cfg.vdec = vdec; + vdec_adapt->vdec = vdec; + vdec->sys_info = &vdec_adapt->dec_prop; + vdec->sys_info_store = vdec_adapt->dec_prop; + vdec->vf_receiver_name = vdec_adapt->recv_name; /* set video format and sys info */ - vdec_set_format(vdec, g_cfg.dec_prop.format); //set by ioctl ??? - set_system_info(vdec); + vdec_set_format(vdec, vdec_adapt->dec_prop.format); set_vdec_mode(vdec); set_vdec_vfm(vdec); @@ -563,7 +541,7 @@ int video_decoder_init(struct aml_vdec_adapt *vdec) set_cfg_info(vdec); /* init hw and gate*/ - ret = enable_hardware(); + ret = enable_hardware(&vdec->port); if (ret < 0) { pr_info("enable hw fail.\n"); goto out; @@ -582,7 +560,7 @@ out: int video_decoder_release(struct aml_vdec_adapt *vdec) { int ret = -1; - struct stream_port_s *port = &g_cfg.port; + struct stream_port_s *port = &vdec->port; ret = vdec_ports_release(port); if (ret < 0) { @@ -591,7 +569,7 @@ int video_decoder_release(struct aml_vdec_adapt *vdec) } /* disable gates */ - ret = disable_hardware(); + ret = disable_hardware(port); if (ret < 0) { pr_info("disable hw fail.\n"); goto out; @@ -600,12 +578,13 @@ out: return ret; } -int vdec_vbuf_write(struct file *file, const char *buf, unsigned int count) +int vdec_vbuf_write(struct aml_vdec_adapt *ada_ctx, + const char *buf, unsigned int count) { int ret = -1; int try_cnt = 100; - struct stream_port_s *port = &g_cfg.port; - struct vdec_s *vdec = g_cfg.vdec; + struct stream_port_s *port = &ada_ctx->port; + struct vdec_s *vdec = ada_ctx->vdec; struct stream_buf_s *pbuf = NULL; if (has_hevc_vdec()) { @@ -622,9 +601,9 @@ int vdec_vbuf_write(struct file *file, const char *buf, unsigned int count) do { if (vdec->port_flag & PORT_FLAG_DRM) - ret = drm_write(file, pbuf, buf, count); + ret = drm_write(ada_ctx->filp, pbuf, buf, count); else - ret = esparser_write(file, pbuf, buf, count); + ret = esparser_write(ada_ctx->filp, pbuf, buf, count); } while (ret == -EAGAIN && try_cnt--); if (slow_input) { @@ -641,9 +620,9 @@ int vdec_vbuf_write(struct file *file, const char *buf, unsigned int count) return ret; } -int is_need_to_buf(void) +int is_need_to_buf(struct aml_vdec_adapt *ada_ctx) { - struct vdec_s *vdec = g_cfg.vdec; + struct vdec_s *vdec = ada_ctx->vdec; if (vdec->input.have_frame_num > 8) return 0; @@ -651,12 +630,12 @@ int is_need_to_buf(void) return 1; } -int vdec_vframe_write(struct file *file, const char *buf, - unsigned int count, unsigned long int timestamp) +int vdec_vframe_write(struct aml_vdec_adapt *ada_ctx, + const char *buf, unsigned int count, unsigned long int timestamp) { int ret = -1; int try_cnt = 10; - struct vdec_s *vdec = g_cfg.vdec; + struct vdec_s *vdec = ada_ctx->vdec; /* set timestamp */ vdec_set_timestamp(vdec, timestamp); @@ -678,33 +657,36 @@ int vdec_vframe_write(struct file *file, const char *buf, /* dump to file */ dump_write(buf, count); #endif - aml_v4l2_debug(1, "vdec_vframe_write, vbuf: %p, size: %u, ret: %d, crc: %x\n", - buf, count, ret, crc32(0, buf, count)); + aml_v4l2_debug(2, "[%d] write frames, vbuf: %p, size: %u, ret: %d, crc: %x", + ada_ctx->ctx->id, buf, count, ret, crc32(0, buf, count)); return ret; } -void aml_decoder_flush(void) +void aml_decoder_flush(struct aml_vdec_adapt *ada_ctx) { - struct vdec_s *vdec = g_cfg.vdec; + struct vdec_s *vdec = ada_ctx->vdec; if (vdec) vdec_set_eos(vdec, true); } -void aml_codec_reset(void) +int aml_codec_reset(struct aml_vdec_adapt *ada_ctx) { - struct vdec_s *vdec = g_cfg.vdec; + struct vdec_s *vdec = ada_ctx->vdec; + int ret = 0; if (vdec) { vdec_set_eos(vdec, false); - vdec_reset(vdec); + ret = vdec_reset(vdec); } + + return ret; } -bool is_decoder_ready(void) +bool is_input_ready(struct aml_vdec_adapt *ada_ctx) { - struct vdec_s *vdec = g_cfg.vdec; + struct vdec_s *vdec = ada_ctx->vdec; int state = VDEC_STATUS_UNINITIALIZED; if (vdec) { diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_adapt.h b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_adapt.h index 9c0b05ba4ad7..e2601495b5e1 100644 --- a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_adapt.h +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_adapt.h @@ -2,10 +2,12 @@ #define VDEC_ADAPT_H #include +#include +#include "../stream_input/parser/streambuf.h" #include "aml_vcodec_drv.h" struct aml_vdec_adapt { - enum vformat_e id; + enum vformat_e format; void *vsi; int32_t failure; uint32_t inst_addr; @@ -14,27 +16,31 @@ struct aml_vdec_adapt { struct platform_device *dev; wait_queue_head_t wq; struct file *filp; - //ipi_handler_t handler; + struct vdec_s *vdec; + struct stream_port_s port; + struct dec_sysinfo dec_prop; + char *recv_name; }; -int video_decoder_init(struct aml_vdec_adapt *vdec); +int video_decoder_init(struct aml_vdec_adapt *ada_ctx); -int video_decoder_release(struct aml_vdec_adapt *vdec); +int video_decoder_release(struct aml_vdec_adapt *ada_ctx); -int vdec_vbuf_write(struct file *file, const char *buf, unsigned int count); +int vdec_vbuf_write(struct aml_vdec_adapt *ada_ctx, + const char *buf, unsigned int count); -int vdec_vframe_write(struct file *file, const char *buf, - unsigned int count, unsigned long int pts); +int vdec_vframe_write(struct aml_vdec_adapt *ada_ctx, + const char *buf, unsigned int count, unsigned long int timestamp); -int is_need_to_buf(void); +int is_need_to_buf(struct aml_vdec_adapt *ada_ctx); -void aml_decoder_flush(void); +void aml_decoder_flush(struct aml_vdec_adapt *ada_ctx); -void aml_codec_reset(void); +int aml_codec_reset(struct aml_vdec_adapt *ada_ctx); extern void dump_write(const char __user *buf, size_t count); -bool is_decoder_ready(void); +bool is_input_ready(struct aml_vdec_adapt *ada_ctx); #endif /* VDEC_ADAPT_H */ diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec.c b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec.c index e33ca62dfdcc..bc6fabcc2b28 100644 --- a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec.c +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec.c @@ -106,15 +106,15 @@ static void aml_vdec_queue_res_chg_event(struct aml_vcodec_ctx *ctx) V4L2_EVENT_SRC_CH_RESOLUTION, }; - aml_v4l2_debug(4, "[%d]", ctx->id); + aml_v4l2_debug(4, "[%d] %s()", ctx->id, __func__); v4l2_event_queue_fh(&ctx->fh, &ev_src_ch); } static void aml_vdec_flush_decoder(struct aml_vcodec_ctx *ctx) { - aml_v4l2_debug(1, "%s() [%d]\n", __FUNCTION__, __LINE__); + aml_v4l2_debug(3, "[%d] %s() [%d]", ctx->id, __func__, __LINE__); - aml_decoder_flush(); + aml_decoder_flush(ctx->ada_ctx); } static void aml_vdec_pic_info_update(struct aml_vcodec_ctx *ctx) @@ -125,34 +125,34 @@ static void aml_vdec_pic_info_update(struct aml_vcodec_ctx *ctx) if (vdec_if_get_param(ctx, GET_PARAM_PIC_INFO, &ctx->last_decoded_picinfo)) { - aml_v4l2_err("[%d]Error!! Cannot get param : GET_PARAM_PICTURE_INFO ERR", + aml_v4l2_err("[%d] Error!! Cannot get param : GET_PARAM_PICTURE_INFO ERR", ctx->id); return; } - if (ctx->last_decoded_picinfo.pic_w == 0 || - ctx->last_decoded_picinfo.pic_h == 0 || - ctx->last_decoded_picinfo.buf_w == 0 || - ctx->last_decoded_picinfo.buf_h == 0) { + if (ctx->last_decoded_picinfo.visible_width == 0 || + ctx->last_decoded_picinfo.visible_height == 0 || + ctx->last_decoded_picinfo.coded_width == 0 || + ctx->last_decoded_picinfo.coded_height == 0) { aml_v4l2_err("Cannot get correct pic info"); return; } - if ((ctx->last_decoded_picinfo.pic_w == ctx->picinfo.pic_w) || - (ctx->last_decoded_picinfo.pic_h == ctx->picinfo.pic_h)) + if ((ctx->last_decoded_picinfo.visible_width == ctx->picinfo.visible_width) || + (ctx->last_decoded_picinfo.visible_height == ctx->picinfo.visible_height)) return; aml_v4l2_debug(4, "[%d]-> new(%d,%d), old(%d,%d), real(%d,%d)", - ctx->id, ctx->last_decoded_picinfo.pic_w, - ctx->last_decoded_picinfo.pic_h, - ctx->picinfo.pic_w, ctx->picinfo.pic_h, - ctx->last_decoded_picinfo.buf_w, - ctx->last_decoded_picinfo.buf_h); + ctx->id, ctx->last_decoded_picinfo.visible_width, + ctx->last_decoded_picinfo.visible_height, + ctx->picinfo.visible_width, ctx->picinfo.visible_height, + ctx->last_decoded_picinfo.coded_width, + ctx->last_decoded_picinfo.coded_width); ret = vdec_if_get_param(ctx, GET_PARAM_DPB_SIZE, &dpbsize); if (dpbsize == 0) - aml_v4l2_err("Incorrect dpb size, ret=%d", ret); + aml_v4l2_err("[%d] Incorrect dpb size, ret=%d", ctx->id, ret); ctx->dpb_size = dpbsize; } @@ -163,14 +163,20 @@ int get_fb_from_queue(struct aml_vcodec_ctx *ctx, struct vdec_fb **out_fb) struct vdec_fb *pfb; struct aml_video_dec_buf *dst_buf_info, *info; struct vb2_v4l2_buffer *dst_vb2_v4l2; + int try_cnt = 10; - aml_v4l2_debug(4,"%s() [%d]\n", __FUNCTION__, __LINE__); + aml_v4l2_debug(4, "[%d] %s() [%d]", ctx->id, __func__, __LINE__); - dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); - if (!dst_buf) { - pr_err("[%d] dst_buf is empty!!\n", ctx->id); + do { + dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); + if (dst_buf) + break; + aml_v4l2_debug(3, "[%d] waitting enough dst buffers.", ctx->id); + msleep(20); + } while (try_cnt--); + + if (!dst_buf) return -1; - } dst_vb2_v4l2 = container_of(dst_buf, struct vb2_v4l2_buffer, vb2_buf); dst_buf_info = container_of(dst_vb2_v4l2, struct aml_video_dec_buf, vb); @@ -179,23 +185,21 @@ int get_fb_from_queue(struct aml_vcodec_ctx *ctx, struct vdec_fb **out_fb) //pfb->base_y.va = vb2_plane_vaddr(dst_buf, 0); pfb->base_y.dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0); pfb->base_y.va = phys_to_virt(dma_to_phys(v4l_get_dev_from_codec_mm(), pfb->base_y.dma_addr)); - pfb->base_y.size = ctx->picinfo.y_bs_sz + ctx->picinfo.y_len_sz; + pfb->base_y.size = ctx->picinfo.y_len_sz; //pfb->base_c.va = vb2_plane_vaddr(dst_buf, 1); pfb->base_c.dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 1); pfb->base_c.va = phys_to_virt(dma_to_phys(v4l_get_dev_from_codec_mm(), pfb->base_c.dma_addr)); - pfb->base_c.size = ctx->picinfo.c_bs_sz + ctx->picinfo.c_len_sz; - pfb->status = 0; + pfb->base_c.size = ctx->picinfo.c_len_sz; + pfb->status = FB_ST_NORMAL; - aml_v4l2_debug(4, - "id=%d Framebuf pfb=%p VA=%p Y_DMA=%pad C_DMA=%pad y_size=%zx, c_size: %zx\n", - dst_buf->index, pfb, - pfb->base_y.va, &pfb->base_y.dma_addr, + aml_v4l2_debug(4, "[%d] id=%d Framebuf pfb=%p VA=%p Y_DMA=%pad C_DMA=%pad y_size=%zx, c_size: %zx", + ctx->id, dst_buf->index, pfb, pfb->base_y.va, &pfb->base_y.dma_addr, &pfb->base_c.dma_addr, pfb->base_y.size, pfb->base_c.size); - mutex_lock(&ctx->lock); + //mutex_lock(&ctx->lock); dst_buf_info->used = true; - mutex_unlock(&ctx->lock); + //mutex_unlock(&ctx->lock); v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); @@ -211,10 +215,10 @@ int put_fb_to_queue(struct aml_vcodec_ctx *ctx, struct vdec_fb *in_fb) { struct aml_video_dec_buf *dstbuf; - pr_info("%s() [%d]\n", __FUNCTION__, __LINE__); + pr_info("[%d] %s() [%d]\n", ctx->id, __func__, __LINE__); if (in_fb == NULL) { - aml_v4l2_debug(4, " No free frame buffer"); + aml_v4l2_debug(4, "[%d] No free frame buffer", ctx->id); return -1; } @@ -228,7 +232,7 @@ int put_fb_to_queue(struct aml_vcodec_ctx *ctx, struct vdec_fb *in_fb) goto out; aml_v4l2_debug(4, - "[%d]status=%x queue id=%d to rdy_queue", + "[%d] status=%x queue id=%d to rdy_queue", ctx->id, in_fb->status, dstbuf->vb.vb2_buf.index); @@ -250,8 +254,6 @@ void trans_vframe_to_user(struct aml_vcodec_ctx *ctx, struct vdec_fb *fb) struct vframe_s *vf = (struct vframe_s *)fb->vf_handle; dstbuf = container_of(fb, struct aml_video_dec_buf, frame_buffer); - if (!dstbuf->used) - return; aml_v4l2_debug(4,"%s() [%d], base_y: %zu, idx: %u\n", __FUNCTION__, __LINE__, fb->base_y.size, dstbuf->vb.vb2_buf.index); @@ -259,40 +261,45 @@ void trans_vframe_to_user(struct aml_vcodec_ctx *ctx, struct vdec_fb *fb) __FUNCTION__, __LINE__, fb->base_c.size, dstbuf->vb.vb2_buf.index); dstbuf->vb.vb2_buf.timestamp = vf->timestamp; - aml_v4l2_debug(4,"%s() [%d], timestamp: %llx\n", __FUNCTION__, __LINE__, - vf->timestamp); + aml_v4l2_debug(4, "[%d] %s() [%d], timestamp: %llx", + ctx->id, __func__, __LINE__, vf->timestamp); vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 0, fb->base_y.bytes_used); vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 1, fb->base_c.bytes_used); dstbuf->ready_to_display = true; - aml_v4l2_debug(4,"%s() [%d], [%d]status=%x queue id=%d to done_list %d\n", - __FUNCTION__, __LINE__, - ctx->id, fb->status, - dstbuf->vb.vb2_buf.index, + aml_v4l2_debug(4, "[%d]status=%x queue id=%d to done_list %d", + ctx->id, fb->status, dstbuf->vb.vb2_buf.index, dstbuf->queued_in_vb2); cnt = atomic_read(&dstbuf->vb.vb2_buf.vb2_queue->owned_by_drv_count); - aml_v4l2_debug(4,"%s() [%d], owned_by_drv_count: %d\n", __FUNCTION__, __LINE__, cnt); - aml_v4l2_debug(4,"%s() [%d], y_va: %p, vf_h: %lx\n", __FUNCTION__, __LINE__, - dstbuf->frame_buffer.base_y.va, dstbuf->frame_buffer.vf_handle); - - if (ctx->state == AML_STATE_FLUSH && - vf->flag == VFRAME_FLAG_EMPTY_FRAME_V4L) { - pr_info("recevie a empty frame after flush.\n"); + aml_v4l2_debug(4, "[%d] %s() [%d], owned_by_drv_count: %d", + ctx->id, __func__, __LINE__, cnt); + aml_v4l2_debug(4, "[%d] %s() [%d], y_va: %p, vf_h: %lx", + ctx->id, __func__, __LINE__, dstbuf->frame_buffer.base_y.va, + dstbuf->frame_buffer.vf_handle); + if (vf->flag == VFRAME_FLAG_EMPTY_FRAME_V4L) { dstbuf->lastframe = true; dstbuf->vb.flags = V4L2_BUF_FLAG_LAST; vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 0, 0); vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 1, 0); ctx->has_receive_eos = true; + pr_info("[%d] recevie a empty frame.\n", ctx->id); } - aml_v4l2_debug(1, "%s() [%d]\n", __FUNCTION__, __LINE__); - v4l2_m2m_buf_done(&dstbuf->vb, VB2_BUF_STATE_DONE); + mutex_lock(&ctx->state_lock); + if (ctx->state == AML_STATE_FLUSHING && + ctx->has_receive_eos) { + ctx->state = AML_STATE_FLUSHED; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_FLUSHED)", + ctx->id, __func__); + } + mutex_unlock(&ctx->state_lock); + ctx->decoded_frame_cnt++; } @@ -300,56 +307,65 @@ static int get_display_buffer(struct aml_vcodec_ctx *ctx, struct vdec_fb **out) { int ret = -1; - aml_v4l2_debug(4, "[%d]", ctx->id); + aml_v4l2_debug(4, "[%d] %s()", ctx->id, __func__); ret = vdec_if_get_param(ctx, GET_PARAM_DISP_FRAME_BUFFER, out); if (ret) { - aml_v4l2_err("[%d]Cannot get param : GET_PARAM_DISP_FRAME_BUFFER", ctx->id); + aml_v4l2_err("[%d] Cannot get param : GET_PARAM_DISP_FRAME_BUFFER", ctx->id); return -1; } if (!*out) { - aml_v4l2_debug(4, "No display frame buffer"); + aml_v4l2_debug(4, "[%d] No display frame buffer", ctx->id); return -1; } - //aml_v4l2_debug(4,"%s() [%d]\n", __FUNCTION__, __LINE__); - return ret; } -static void try_to_capture(struct aml_vcodec_ctx *ctx) +static int is_vdec_ready(struct aml_vcodec_ctx *ctx) { - int ret = -1; - int try_cnt = 100; - struct vdec_fb *fb = NULL; - struct aml_video_dec_buf *dstbuf; - int cnt = 0; + struct aml_vcodec_dev *dev = ctx->dev; - do { - ret = get_display_buffer(ctx, &fb); - if (ret) { - aml_v4l2_debug(4,"%s() [%d], the que have no disp buf,ret: %d\n", - __FUNCTION__, __LINE__, ret); - break; + if (!is_input_ready(ctx->ada_ctx)) { + pr_err("[%d] %s() the decoder intput has not ready.\n", + ctx->id, __func__); + v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); + return 0; + } + + 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->dpb_size) { + aml_v4l2_debug(4, "[%d] Not enough dst bufs, num: %d.\n", + 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; } - dstbuf = container_of(fb, struct aml_video_dec_buf, frame_buffer); - dstbuf->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE;//need to change status - cnt = atomic_read(&dstbuf->vb.vb2_buf.vb2_queue->owned_by_drv_count); - aml_v4l2_debug(1, "%s() [%d], cnt: %d\n", __FUNCTION__, __LINE__, cnt); + mutex_lock(&ctx->state_lock); + if (ctx->state == AML_STATE_PROBE) { + ctx->state = AML_STATE_READY; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_READY)", + ctx->id, __func__); + } + mutex_unlock(&ctx->state_lock); + } - if (cnt) - trans_vframe_to_user(ctx, fb); + mutex_lock(&ctx->state_lock); + if (ctx->state == AML_STATE_READY) { + ctx->state = AML_STATE_ACTIVE; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ACTIVE)", + ctx->id, __func__); + } + mutex_unlock(&ctx->state_lock); - //msleep(300); - //video_vf_put(fb);//recycle video buf - - /*ret = put_fb_to_queue(ctx, fb); - if (ret) - aml_v4l2_debug(4,"%s() [%d], put_fb_to_queue fail.\n", - __FUNCTION__, __LINE__);*/ - } while(try_cnt--); + return 1; } static void aml_vdec_worker(struct work_struct *work) @@ -364,20 +380,28 @@ static void aml_vdec_worker(struct work_struct *work) struct aml_video_dec_buf *src_buf_info; struct vb2_v4l2_buffer *src_vb2_v4l2; - aml_v4l2_debug(4,"entry [%d] [%s]\n", __LINE__, __FUNCTION__); + aml_v4l2_debug(4, "[%d] entry [%d] [%s]", ctx->id, __LINE__, __func__); - if ((ctx->state == AML_STATE_FLUSH || - ctx->state == AML_STATE_RESET) && - !is_decoder_ready()) { - pr_err("[%d] [%s] the decoder has no ready.\n", - __LINE__, __FUNCTION__); + aml_vdec_lock(ctx); + + if (ctx->state < AML_STATE_INIT || + ctx->state > AML_STATE_FLUSHED) { + v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); + aml_vdec_unlock(ctx); + return; + } + + if (!is_vdec_ready(ctx)) { + pr_err("[%d] %s() the decoder has not ready.\n", + ctx->id, __func__); + aml_vdec_unlock(ctx); return; } src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); if (src_buf == NULL) { - v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); - aml_v4l2_debug(0, "[%d] src_buf empty!!", ctx->id); + pr_err("[%d] src_buf empty!\n", ctx->id); + aml_vdec_unlock(ctx); return; } @@ -386,10 +410,23 @@ 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(0, "Got empty flush input buffer."); + 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); + + /* sets eos data for vdec input. */ + 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)", + ctx->id, __func__); + } + mutex_unlock(&ctx->state_lock); + + aml_vdec_unlock(ctx); return; } @@ -402,6 +439,7 @@ static void aml_vdec_worker(struct work_struct *work) v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); aml_v4l2_err("[%d] id=%d src_addr is NULL!!", ctx->id, src_buf->index); + aml_vdec_unlock(ctx); return; } aml_v4l2_debug(4, "[%d] Bitstream VA=%p DMA=%pad Size=%zx vb=%p", @@ -410,10 +448,10 @@ static void aml_vdec_worker(struct work_struct *work) src_buf_info->used = true; //pr_err("%s() [%d], size: 0x%zx, crc: 0x%x\n", - //__FUNCTION__, __LINE__, buf.size, crc32(0, buf.va, buf.size)); + //__func__, __LINE__, buf.size, crc32(0, buf.va, buf.size)); /* pts = (time / 10e6) * (90k / fps) */ - aml_v4l2_debug(4,"[%d] [%s] timestamp: 0x%llx\n", __LINE__, __FUNCTION__, + aml_v4l2_debug(4, "[%d] %s() timestamp: 0x%llx", ctx->id , __func__, src_buf->timestamp); ret = vdec_if_decode(ctx, &buf, src_buf->timestamp, &res_chg); @@ -426,13 +464,14 @@ static void aml_vdec_worker(struct work_struct *work) v4l2_m2m_buf_done(&src_buf_info->vb, VB2_BUF_STATE_DONE); } else if (ret == -EAGAIN) { v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); + aml_vdec_unlock(ctx); return; } else { src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); if (ret == -EIO) { - mutex_lock(&ctx->lock); + //mutex_lock(&ctx->lock); src_buf_info->error = true; - mutex_unlock(&ctx->lock); + //mutex_unlock(&ctx->lock); } v4l2_m2m_buf_done(&src_buf_info->vb, VB2_BUF_STATE_ERROR); } @@ -457,55 +496,160 @@ static void aml_vdec_worker(struct work_struct *work) } v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); -} - -static void aml_vdec_worker_vf(struct work_struct *work) -{ - struct aml_vcodec_ctx *ctx = - container_of(work, struct aml_vcodec_ctx, decode_work_vf); - - aml_v4l2_debug(1, "[%d] [%s], state: %d \n", __LINE__, __FUNCTION__, ctx->state); - - if (ctx->state != AML_STATE_ABORT && - ctx->state != AML_STATE_FREE) - try_to_capture(ctx); + aml_vdec_unlock(ctx); } static void aml_reset_worker(struct work_struct *work) { struct aml_vcodec_ctx *ctx = container_of(work, struct aml_vcodec_ctx, reset_work); - int try_cnt = 10; - int buf_ready_num; - - aml_v4l2_debug(1, "[%d] [%s] \n", __LINE__, __FUNCTION__); + struct aml_video_dec_buf *buf = NULL; aml_vdec_lock(ctx); - do { - buf_ready_num = v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx); - if (buf_ready_num < ctx->dpb_size) { - aml_v4l2_debug(4,"try to get more bufs, num: %d.\n", - buf_ready_num); - msleep(20); - } - } while (buf_ready_num < ctx->dpb_size && try_cnt--); - - if (buf_ready_num < ctx->dpb_size) { + if (ctx->state == AML_STATE_ABORT) { + pr_err("[%d] %s() the decoder will be exited.\n", + ctx->id, __func__); aml_vdec_unlock(ctx); - pr_err("the buf has not enough to be used in decoder.\n"); return; } - aml_codec_reset(); + /* fast enque capture buffers. */ + list_for_each_entry(buf, &ctx->capture_list, node) { + if (buf->que_in_m2m) + v4l2_m2m_buf_queue(ctx->m2m_ctx, &buf->vb); + } - ctx->state = AML_STATE_HEADER; + if (aml_codec_reset(ctx->ada_ctx)) { + ctx->state = AML_STATE_ABORT; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ABORT)", + ctx->id, __func__); + aml_vdec_unlock(ctx); + return; + } - v4l2_m2m_try_schedule(ctx->m2m_ctx); + mutex_lock(&ctx->state_lock); + if (ctx->state == AML_STATE_RESET) { + ctx->state = AML_STATE_READY; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_READY)", + ctx->id, __func__); + + v4l2_m2m_try_schedule(ctx->m2m_ctx); + } + mutex_unlock(&ctx->state_lock); aml_vdec_unlock(ctx); } +void try_to_capture(struct aml_vcodec_ctx *ctx) +{ + int ret = 0; + struct vdec_fb *fb = NULL; + + ret = get_display_buffer(ctx, &fb); + if (ret) { + aml_v4l2_debug(4, "[%d] %s() [%d], the que have no disp buf,ret: %d", + ctx->id, __func__, __LINE__, ret); + return; + } + + trans_vframe_to_user(ctx, fb); +} +EXPORT_SYMBOL_GPL(try_to_capture); + +static int vdec_thread(void *data) +{ + struct aml_vdec_thread *thread = + (struct aml_vdec_thread *) data; + struct aml_vcodec_ctx *ctx = + (struct aml_vcodec_ctx *) thread->priv; + + for (;;) { + aml_v4l2_debug(3, "[%d] %s() state: %d", ctx->id, + __func__, ctx->state); + + if (down_interruptible(&thread->sem)) + break; + + if (thread->stop) + break; + + thread->func(ctx); + } + + while (!kthread_should_stop()) { + set_current_state(TASK_INTERRUPTIBLE); + schedule(); + } + + return 0; +} + +void aml_thread_notify(struct aml_vcodec_ctx *ctx, + enum aml_thread_type type) +{ + struct aml_vdec_thread *thread = NULL; + + list_for_each_entry(thread, &ctx->vdec_thread_list, node) { + if (thread->task == NULL) + continue; + + if (thread->type == type) + up(&thread->sem); + } +} +EXPORT_SYMBOL_GPL(aml_thread_notify); + +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; + int ret = 0; + + thread = kzalloc(sizeof(*thread), GFP_KERNEL); + if (thread == NULL) + return -ENOMEM; + + thread->type = type; + thread->func = func; + thread->priv = ctx; + sema_init(&thread->sem, 0); + + thread->task = kthread_run(vdec_thread, thread, "aml-%s", thread_name); + if (IS_ERR(thread->task)) { + ret = PTR_ERR(thread->task); + thread->task = NULL; + goto err; + } + + list_add(&thread->node, &ctx->vdec_thread_list); + + return 0; + +err: + kfree(thread); + + return ret; +} +EXPORT_SYMBOL_GPL(aml_thread_start); + +void aml_thread_stop(struct aml_vcodec_ctx *ctx) +{ + struct aml_vdec_thread *thread = NULL; + + while (!list_empty(&ctx->vdec_thread_list)) { + thread = list_entry(ctx->vdec_thread_list.next, + struct aml_vdec_thread, node); + list_del(&thread->node); + thread->stop = true; + up(&thread->sem); + kthread_stop(thread->task); + thread->task = NULL; + kfree(thread); + } +} +EXPORT_SYMBOL_GPL(aml_thread_stop); + static int vidioc_try_decoder_cmd(struct file *file, void *priv, struct v4l2_decoder_cmd *cmd) { @@ -534,23 +678,25 @@ static int vidioc_decoder_cmd(struct file *file, void *priv, if (ret) return ret; - aml_v4l2_debug(1, "[%d] [%s], cmd: %u\n", __LINE__, __FUNCTION__, cmd->cmd); + aml_v4l2_debug(3, "[%d] %s() [%d], cmd: %u", + ctx->id, __func__, __LINE__, cmd->cmd); dst_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); switch (cmd->cmd) { case V4L2_DEC_CMD_STOP: - if (ctx->state != AML_STATE_HEADER) + if (ctx->state != AML_STATE_ACTIVE) return 0; src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); if (!vb2_is_streaming(src_vq)) { - aml_v4l2_debug(0, "Output stream is off. No need to flush."); + pr_err("[%d] Output stream is off. No need to flush.\n", ctx->id); return 0; } + if (!vb2_is_streaming(dst_vq)) { - aml_v4l2_debug(0, "Capture stream is off. No need to flush."); + pr_err("[%d] Capture stream is off. No need to flush.\n", ctx->id); return 0; } @@ -558,14 +704,10 @@ static int vidioc_decoder_cmd(struct file *file, void *priv, v4l2_m2m_buf_queue(ctx->m2m_ctx, &ctx->empty_flush_buf->vb); v4l2_m2m_try_schedule(ctx->m2m_ctx);//pay attention - /* flush dst */ - aml_vdec_flush_decoder(ctx); - - ctx->state = AML_STATE_FLUSH; break; case V4L2_DEC_CMD_START: - aml_v4l2_debug(4,"[%d] [%s] V4L2_DEC_CMD_START \n", __LINE__, __FUNCTION__); + aml_v4l2_debug(4, "[%d] CMD V4L2_DEC_CMD_START ", ctx->id); vb2_clear_last_buffer_dequeued(dst_vq);//pay attention break; @@ -589,12 +731,16 @@ static int vidioc_decoder_streamon(struct file *file, void *priv, q = v4l2_m2m_get_vq(fh->m2m_ctx, i); - if (ctx->state == AML_STATE_FLUSH) { + mutex_lock(&ctx->state_lock); + if (ctx->state == AML_STATE_FLUSHED) { if (!V4L2_TYPE_IS_OUTPUT(q->type)) { - queue_work(dev->reset_workqueue, &ctx->reset_work); ctx->state = AML_STATE_RESET; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_RESET)", + ctx->id, __func__); + queue_work(dev->reset_workqueue, &ctx->reset_work); } } + mutex_unlock(&ctx->state_lock); return ret; } @@ -611,8 +757,15 @@ void aml_vdec_lock(struct aml_vcodec_ctx *ctx) void aml_vcodec_dec_release(struct aml_vcodec_ctx *ctx) { + aml_vdec_lock(ctx); + + ctx->state = AML_STATE_ABORT; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ABORT)", + ctx->id, __func__); + vdec_if_deinit(ctx); - ctx->state = AML_STATE_FREE; + + aml_vdec_unlock(ctx); } void aml_vcodec_dec_set_default_params(struct aml_vcodec_ctx *ctx) @@ -623,7 +776,6 @@ void aml_vcodec_dec_set_default_params(struct aml_vcodec_ctx *ctx) ctx->fh.m2m_ctx = ctx->m2m_ctx; ctx->fh.ctrl_handler = &ctx->ctrl_hdl; INIT_WORK(&ctx->decode_work, aml_vdec_worker); - INIT_WORK(&ctx->decode_work_vf, aml_vdec_worker_vf); INIT_WORK(&ctx->reset_work, aml_reset_worker); ctx->colorspace = V4L2_COLORSPACE_REC709; ctx->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; @@ -661,6 +813,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->state = AML_STATE_IDLE; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_IDLE)", + ctx->id, __func__); } static int vidioc_vdec_qbuf(struct file *file, void *priv, @@ -688,12 +844,6 @@ static int vidioc_vdec_dqbuf(struct file *file, void *priv, return -EIO; } - /*if (V4L2_TYPE_IS_OUTPUT(buf->type)) { - aml_v4l2_debug(4,"%s() [%d]\n", __FUNCTION__, __LINE__); - wait_event_interruptible_timeout(ctx->wq, is_need_to_buf(), - msecs_to_jiffies(200)); - }*/ - return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); } @@ -744,7 +894,7 @@ static int vidioc_try_fmt(struct v4l2_format *f, struct aml_video_fmt *fmt) * Find next closer width align 64, heign align 64, size align * 64 rectangle * Note: This only get default value, the real HW needed value - * only available when ctx in AML_STATE_HEADER state + * only available when ctx in AML_STATE_PROBE state */ tmp_w = pix_fmt_mp->width; tmp_h = pix_fmt_mp->height; @@ -839,14 +989,14 @@ static int vidioc_vdec_g_selection(struct file *file, void *priv, case V4L2_SEL_TGT_COMPOSE_DEFAULT: s->r.left = 0; s->r.top = 0; - s->r.width = ctx->picinfo.pic_w; - s->r.height = ctx->picinfo.pic_h; + s->r.width = ctx->picinfo.visible_width; + s->r.height = ctx->picinfo.visible_height; break; case V4L2_SEL_TGT_COMPOSE_BOUNDS: s->r.left = 0; s->r.top = 0; - s->r.width = ctx->picinfo.buf_w; - s->r.height = ctx->picinfo.buf_h; + s->r.width = ctx->picinfo.coded_width; + s->r.height = ctx->picinfo.coded_height; break; case V4L2_SEL_TGT_COMPOSE: if (vdec_if_get_param(ctx, GET_PARAM_CROP_INFO, &(s->r))) { @@ -861,7 +1011,7 @@ static int vidioc_vdec_g_selection(struct file *file, void *priv, return -EINVAL; } - if (ctx->state < AML_STATE_HEADER) { + if (ctx->state < AML_STATE_PROBE) { /* set to default value if header info not ready yet*/ s->r.left = 0; s->r.top = 0; @@ -885,8 +1035,8 @@ static int vidioc_vdec_s_selection(struct file *file, void *priv, case V4L2_SEL_TGT_COMPOSE: s->r.left = 0; s->r.top = 0; - s->r.width = ctx->picinfo.pic_w; - s->r.height = ctx->picinfo.pic_h; + s->r.width = ctx->picinfo.visible_width; + s->r.height = ctx->picinfo.visible_height; break; default: return -EINVAL; @@ -904,7 +1054,7 @@ static int vidioc_vdec_s_fmt(struct file *file, void *priv, int ret = 0; struct aml_video_fmt *fmt; - aml_v4l2_debug(4, "[%d]", ctx->id); + aml_v4l2_debug(4, "[%d] %s()", ctx->id, __func__); q_data = aml_vdec_get_q_data(ctx, f->type); if (!q_data) @@ -913,12 +1063,12 @@ static int vidioc_vdec_s_fmt(struct file *file, void *priv, pix_mp = &f->fmt.pix_mp; if ((f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) && vb2_is_busy(&ctx->m2m_ctx->out_q_ctx.q)) { - aml_v4l2_err("out_q_ctx buffers already requested"); + aml_v4l2_err("[%d] out_q_ctx buffers already requested", ctx->id); } if ((f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) && vb2_is_busy(&ctx->m2m_ctx->cap_q_ctx.q)) { - aml_v4l2_err("cap_q_ctx buffers already requested"); + aml_v4l2_err("[%d] cap_q_ctx buffers already requested", ctx->id); } fmt = aml_vdec_find_format(f); @@ -941,8 +1091,8 @@ static int vidioc_vdec_s_fmt(struct file *file, void *priv, q_data->coded_width = pix_mp->width; q_data->coded_height = pix_mp->height; - aml_v4l2_debug(4, "%s() [%d], w: %d, h: %d, size: %d\n", - __func__, __LINE__, pix_mp->width, pix_mp->height, + aml_v4l2_debug(4, "[%d] %s() [%d], w: %d, h: %d, size: %d", + ctx->id, __func__, __LINE__, pix_mp->width, pix_mp->height, pix_mp->plane_fmt[0].sizeimage); ctx->colorspace = f->fmt.pix_mp.colorspace; @@ -950,15 +1100,20 @@ static int vidioc_vdec_s_fmt(struct file *file, void *priv, ctx->quantization = f->fmt.pix_mp.quantization; ctx->xfer_func = f->fmt.pix_mp.xfer_func; - if (ctx->state == AML_STATE_FREE) { + mutex_lock(&ctx->state_lock); + if (ctx->state == AML_STATE_IDLE) { ret = vdec_if_init(ctx, q_data->fmt->fourcc); if (ret) { aml_v4l2_err("[%d]: vdec_if_init() fail ret=%d", ctx->id, ret); + mutex_unlock(&ctx->state_lock); return -EINVAL; } ctx->state = AML_STATE_INIT; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_INIT)", + ctx->id, __func__); } + mutex_unlock(&ctx->state_lock); } return 0; @@ -981,14 +1136,14 @@ static int vidioc_enum_framesizes(struct file *file, void *priv, fsize->stepwise = aml_vdec_framesizes[i].stepwise; if (!(ctx->dev->dec_capability & VCODEC_CAPABILITY_4K_DISABLED)) { - aml_v4l2_debug(4, "4K is enabled"); + aml_v4l2_debug(4, "[%d] 4K is enabled", ctx->id); fsize->stepwise.max_width = VCODEC_DEC_4K_CODED_WIDTH; fsize->stepwise.max_height = VCODEC_DEC_4K_CODED_HEIGHT; } - aml_v4l2_debug(4, "%x, %d %d %d %d %d %d", - ctx->dev->dec_capability, + aml_v4l2_debug(4, "[%d] %x, %d %d %d %d %d %d", + ctx->id, ctx->dev->dec_capability, fsize->stepwise.min_width, fsize->stepwise.max_width, fsize->stepwise.step_width, @@ -1049,7 +1204,7 @@ static int vidioc_vdec_g_fmt(struct file *file, void *priv, vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); if (!vq) { - aml_v4l2_err("no vb2 queue for type=%d", f->type); + aml_v4l2_err("[%d] no vb2 queue for type=%d", ctx->id, f->type); return -EINVAL; } @@ -1062,7 +1217,7 @@ static int vidioc_vdec_g_fmt(struct file *file, void *priv, pix_mp->xfer_func = ctx->xfer_func; if ((f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) && - (ctx->state >= AML_STATE_HEADER)) { + (ctx->state >= AML_STATE_PROBE)) { /* Until STREAMOFF is called on the CAPTURE queue * (acknowledging the event), the driver operates as if * the resolution hasn't changed yet. @@ -1074,11 +1229,11 @@ static int vidioc_vdec_g_fmt(struct file *file, void *priv, q_data->sizeimage[1] = ctx->picinfo.c_len_sz; /* it is used for alloc the EGL image buffer size. */ - q_data->coded_width = ctx->picinfo.pic_w; - q_data->coded_height = ctx->picinfo.pic_h; + q_data->coded_width = ctx->picinfo.coded_width; + q_data->coded_height = ctx->picinfo.coded_height; - q_data->bytesperline[0] = ctx->picinfo.buf_w; - q_data->bytesperline[1] = ctx->picinfo.buf_w; + q_data->bytesperline[0] = ctx->picinfo.coded_width; + q_data->bytesperline[1] = ctx->picinfo.coded_height; /* * Width and height are set to the dimensions @@ -1099,7 +1254,6 @@ static int vidioc_vdec_g_fmt(struct file *file, void *priv, pix_mp->plane_fmt[0].sizeimage = q_data->sizeimage[0]; pix_mp->plane_fmt[1].bytesperline = q_data->bytesperline[1]; pix_mp->plane_fmt[1].sizeimage = q_data->sizeimage[1]; - } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { /* * This is run on OUTPUT @@ -1153,7 +1307,7 @@ static int vb2ops_vdec_queue_setup(struct vb2_queue *vq, q_data = aml_vdec_get_q_data(ctx, vq->type); if (q_data == NULL) { - aml_v4l2_err("vq->type=%d err\n", vq->type); + aml_v4l2_err("[%d] vq->type=%d err", ctx->id, vq->type); return -EINVAL; } @@ -1177,7 +1331,7 @@ static int vb2ops_vdec_queue_setup(struct vb2_queue *vq, } } - pr_info("[%d], type: %d, plane: %d, buf cnt: %d, size: [Y: %u, C: %u]\n", + pr_info("[%d] type: %d, plane: %d, buf cnt: %d, size: [Y: %u, C: %u]\n", ctx->id, vq->type, *nplanes, *nbuffers, sizes[0], sizes[1]); return 0; @@ -1196,8 +1350,8 @@ static int vb2ops_vdec_buf_prepare(struct vb2_buffer *vb) for (i = 0; i < q_data->fmt->num_planes; i++) { if (vb2_plane_size(vb, i) < q_data->sizeimage[i]) { - aml_v4l2_err("data will not fit into plane %d (%lu < %d)", - i, vb2_plane_size(vb, i), + aml_v4l2_err("[%d] data will not fit into plane %d (%lu < %d)", + ctx->id, i, vb2_plane_size(vb, i), q_data->sizeimage[i]); } } @@ -1216,29 +1370,36 @@ static void vb2ops_vdec_buf_queue(struct vb2_buffer *vb) vb2_v4l2 = to_vb2_v4l2_buffer(vb); buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb); - aml_v4l2_debug(1, "%s(),[%d], vb: %p, type: %d, idx: %d, state: %d, used: %d\n", - __FUNCTION__, __LINE__, vb, vb->vb2_queue->type, + aml_v4l2_debug(3, "[%d] %s(), vb: %p, type: %d, idx: %d, state: %d, used: %d", + ctx->id, __func__, vb, vb->vb2_queue->type, vb->index, vb->state, buf->used); /* * check if this buffer is ready to be used after decode */ - if (vb->vb2_queue->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + if (!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) { + aml_v4l2_debug(3, "[%d] %s() [%d], y_va: %p, vf_h: %lx, state: %d", ctx->id, + __func__, __LINE__, buf->frame_buffer.base_y.va, + buf->frame_buffer.vf_handle, buf->frame_buffer.status); - aml_v4l2_debug(4, "%s() [%d], y_va: %p, vf_h: %lx\n", __FUNCTION__, __LINE__, - buf->frame_buffer.base_y.va, buf->frame_buffer.vf_handle); - - if (buf->used == false) { + if (!buf->que_in_m2m && buf->frame_buffer.status == FB_ST_NORMAL) { + aml_v4l2_debug(3, "[%d] enque capture buf idx %d, %p\n", + ctx->id, vb->index, vb); 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; - } else { + + /*save capture bufs to be used for resetting config.*/ + list_add(&buf->node, &ctx->capture_list); + } else if (buf->frame_buffer.status == FB_ST_DISPLAY) { buf->queued_in_vb2 = false; buf->queued_in_v4l2 = true; buf->ready_to_display = false; /* recycle vf */ - video_vf_put(&buf->frame_buffer); + video_vf_put(ctx->ada_ctx->recv_name, + &buf->frame_buffer, ctx->id); } return; } @@ -1255,7 +1416,7 @@ static void vb2ops_vdec_buf_queue(struct vb2_buffer *vb) buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb); if (buf->lastframe) { /* This shouldn't happen. Just in case. */ - aml_v4l2_err("Invalid flush buffer.\n"); + aml_v4l2_err("[%d] Invalid flush buffer.", ctx->id); v4l2_m2m_src_buf_remove(ctx->m2m_ctx); return; } @@ -1280,11 +1441,13 @@ static void vb2ops_vdec_buf_queue(struct vb2_buffer *vb) ctx->last_decoded_picinfo = ctx->picinfo; aml_vdec_queue_res_chg_event(ctx); - ctx->state = AML_STATE_HEADER; - - aml_v4l2_debug(1, "pic info, w: %u, h: %u, y_s: %u, c_s: %u, DPB: %u\n", - ctx->picinfo.pic_w, ctx->picinfo.pic_h, ctx->picinfo.y_len_sz, - ctx->picinfo.c_len_sz, ctx->dpb_size); + mutex_lock(&ctx->state_lock); + if (ctx->state == AML_STATE_INIT) { + ctx->state = AML_STATE_PROBE; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_PROBE)", + ctx->id, __func__); + } + mutex_unlock(&ctx->state_lock); } static void vb2ops_vdec_buf_finish(struct vb2_buffer *vb) @@ -1294,39 +1457,43 @@ static void vb2ops_vdec_buf_finish(struct vb2_buffer *vb) struct aml_video_dec_buf *buf = NULL; bool buf_error; - //pr_err("entry [%d] [%s]\n", __LINE__, __FUNCTION__); - vb2_v4l2 = container_of(vb, struct vb2_v4l2_buffer, vb2_buf); buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb); - mutex_lock(&ctx->lock); + //mutex_lock(&ctx->lock); if (vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { buf->queued_in_v4l2 = false; buf->queued_in_vb2 = false; } buf_error = buf->error; - mutex_unlock(&ctx->lock); + //mutex_unlock(&ctx->lock); if (buf_error) { - aml_v4l2_err("Unrecoverable error on buffer."); + aml_v4l2_err("[%d] Unrecoverable error on buffer.", ctx->id); ctx->state = AML_STATE_ABORT; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ABORT)", + ctx->id, __func__); } } static int vb2ops_vdec_buf_init(struct vb2_buffer *vb) { + struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); struct vb2_v4l2_buffer *vb2_v4l2 = container_of(vb, struct vb2_v4l2_buffer, vb2_buf); struct aml_video_dec_buf *buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb); unsigned int size, phy_addr = 0; + char *owner = __getname(); - aml_v4l2_debug(4, "(%d) id=%d", vb->vb2_queue->type, vb->index); + aml_v4l2_debug(4, "[%d] (%d) id=%d", + ctx->id, vb->vb2_queue->type, vb->index); if (vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { buf->used = false; buf->ready_to_display = false; buf->queued_in_v4l2 = false; + buf->frame_buffer.status = FB_ST_NORMAL; } else { buf->lastframe = false; } @@ -1335,31 +1502,42 @@ static int vb2ops_vdec_buf_init(struct vb2_buffer *vb) if (V4L2_TYPE_IS_OUTPUT(vb->type)) { size = vb->planes[0].length; phy_addr = vb2_dma_contig_plane_dma_addr(vb, 0); - buf->mem[0] = v4l_reqbufs_from_codec_mm("v4l-input", - phy_addr, size, vb->index); - aml_v4l2_debug(1, "IN alloc, addr: %x, size: %u, idx: %u\n", - phy_addr, size, vb->index); + snprintf(owner, PATH_MAX, "%s-%d", "v4l-input", ctx->id); + strncpy(buf->mem_onwer, owner, sizeof(buf->mem_onwer)); + buf->mem_onwer[sizeof(buf->mem_onwer) - 1] = '\0'; + + buf->mem[0] = v4l_reqbufs_from_codec_mm(buf->mem_onwer, + phy_addr, size, vb->index); + aml_v4l2_debug(3, "[%d] IN alloc, addr: %x, size: %u, idx: %u", + ctx->id, phy_addr, size, vb->index); } else { size = vb->planes[0].length; phy_addr = vb2_dma_contig_plane_dma_addr(vb, 0); - buf->mem[0] = v4l_reqbufs_from_codec_mm("v4l-output", - phy_addr, size, vb->index); - aml_v4l2_debug(1, "OUT Y alloc, addr: %x, size: %u, idx: %u\n", + snprintf(owner, PATH_MAX, "%s-%d", "v4l-output", ctx->id); + strncpy(buf->mem_onwer, owner, sizeof(buf->mem_onwer)); + buf->mem_onwer[sizeof(buf->mem_onwer) - 1] = '\0'; + + buf->mem[0] = v4l_reqbufs_from_codec_mm(buf->mem_onwer, phy_addr, size, vb->index); + aml_v4l2_debug(3, "[%d] OUT Y alloc, addr: %x, size: %u, idx: %u", + ctx->id, phy_addr, size, vb->index); size = vb->planes[1].length; phy_addr = vb2_dma_contig_plane_dma_addr(vb, 1); - buf->mem[1] = v4l_reqbufs_from_codec_mm("v4l-output", - phy_addr, size, vb->index); - aml_v4l2_debug(1, "OUT C alloc, addr: %x, size: %u, idx: %u\n", - phy_addr, size, vb->index); + buf->mem[1] = v4l_reqbufs_from_codec_mm(buf->mem_onwer, + phy_addr, size, vb->index); + aml_v4l2_debug(3, "[%d] OUT C alloc, addr: %x, size: %u, idx: %u", + ctx->id, phy_addr, size, vb->index); } + __putname(owner); + return 0; } static void codec_mm_bufs_cnt_clean(struct vb2_queue *q) { + struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(q); struct vb2_v4l2_buffer *vb2_v4l2 = NULL; struct aml_video_dec_buf *buf = NULL; int i; @@ -1371,23 +1549,23 @@ static void codec_mm_bufs_cnt_clean(struct vb2_queue *q) return; if (V4L2_TYPE_IS_OUTPUT(q->bufs[i]->type)) { - v4l_freebufs_back_to_codec_mm("v4l-input", buf->mem[0]); - buf->mem[0] = NULL; + v4l_freebufs_back_to_codec_mm(buf->mem_onwer, buf->mem[0]); - aml_v4l2_debug(1, "IN clean, addr: %lx, size: %u, idx: %u\n", - buf->mem[0]->phy_addr, buf->mem[0]->buffer_size, i); + aml_v4l2_debug(3, "[%d] IN clean, addr: %lx, size: %u, idx: %u", + ctx->id, buf->mem[0]->phy_addr, buf->mem[0]->buffer_size, i); + buf->mem[0] = NULL; continue; } - v4l_freebufs_back_to_codec_mm("v4l-output", buf->mem[0]); - v4l_freebufs_back_to_codec_mm("v4l-output", buf->mem[1]); + v4l_freebufs_back_to_codec_mm(buf->mem_onwer, buf->mem[0]); + v4l_freebufs_back_to_codec_mm(buf->mem_onwer, buf->mem[1]); + + aml_v4l2_debug(3, "[%d] OUT Y clean, addr: %lx, size: %u, idx: %u", + ctx->id, buf->mem[0]->phy_addr, buf->mem[0]->buffer_size, i); + aml_v4l2_debug(3, "[%d] OUT C clean, addr: %lx, size: %u, idx: %u", + ctx->id, buf->mem[1]->phy_addr, buf->mem[1]->buffer_size, i); buf->mem[0] = NULL; buf->mem[1] = NULL; - - aml_v4l2_debug(1, "OUT Y clean, addr: %lx, size: %u, idx: %u\n", - buf->mem[0]->phy_addr, buf->mem[0]->buffer_size, i); - aml_v4l2_debug(1, "OUT C clean, addr: %lx, size: %u, idx: %u\n", - buf->mem[1]->phy_addr, buf->mem[1]->buffer_size, i); } } @@ -1403,70 +1581,31 @@ static int vb2ops_vdec_start_streaming(struct vb2_queue *q, unsigned int count) static void vb2ops_vdec_stop_streaming(struct vb2_queue *q) { - struct vb2_buffer *src_buf = NULL, *dst_buf = NULL; + struct aml_video_dec_buf *buf = NULL; + struct vb2_v4l2_buffer *vb2_v4l2 = NULL; struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(q); int i; - aml_v4l2_debug(1, "[%d] [%s], [%d] (%d) state=(%x) frame_cnt=%d\n", - __LINE__, __FUNCTION__, ctx->id, q->type, - ctx->state, ctx->decoded_frame_cnt); + aml_v4l2_debug(3, "[%d] (%d) state=(%x) frame_cnt=%d", + ctx->id, q->type, ctx->state, ctx->decoded_frame_cnt); codec_mm_bufs_cnt_clean(q); - if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { - while ((src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx))) { - struct vb2_v4l2_buffer *vb2_v4l2 = NULL; - struct aml_video_dec_buf *buf_info = NULL; - int cnt; - - vb2_v4l2 = to_vb2_v4l2_buffer(src_buf); - buf_info = container_of(vb2_v4l2, struct aml_video_dec_buf, vb); - - cnt = atomic_read(&src_buf->vb2_queue->owned_by_drv_count); - aml_v4l2_debug(4,"%s() [%d], owned_by_drv_count: %d, lastframe: %d\n", - __FUNCTION__, __LINE__, cnt, buf_info->lastframe); - - if (!buf_info->lastframe) - v4l2_m2m_buf_done(vb2_v4l2, VB2_BUF_STATE_QUEUED); - } - + if (V4L2_TYPE_IS_OUTPUT(q->type)) { + while (v4l2_m2m_src_buf_remove(ctx->m2m_ctx)); return; } - while ((dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx))) { - int cnt; + while (v4l2_m2m_dst_buf_remove(ctx->m2m_ctx)); - vb2_set_plane_payload(dst_buf, 0, 0); - vb2_set_plane_payload(dst_buf, 1, 0); - - cnt = atomic_read(&dst_buf->vb2_queue->owned_by_drv_count); - - aml_v4l2_debug(4,"%s() [%d], state: %d, cnt: %d\n", - __FUNCTION__, __LINE__, dst_buf->state, cnt); - - if (dst_buf->state == VB2_BUF_STATE_DONE || !cnt) { //discard vframe data - dst_buf->state = VB2_BUF_STATE_ACTIVE; - continue; - } - - dst_buf->state = VB2_BUF_STATE_ACTIVE;//need to change status - - v4l2_m2m_buf_done(to_vb2_v4l2_buffer(dst_buf), VB2_BUF_STATE_QUEUED); - } - - /*capture*/ for (i = 0; i < q->num_buffers; ++i) { - struct vb2_v4l2_buffer *vb2_v4l2 = NULL; - struct aml_video_dec_buf *buf_info = NULL; - - if (q->bufs[i]->state == VB2_BUF_STATE_ACTIVE) - vb2_buffer_done(q->bufs[i], VB2_BUF_STATE_QUEUED); - + if (q->bufs[i]->state == VB2_BUF_STATE_ACTIVE) { + q->bufs[i]->state = VB2_BUF_STATE_DEQUEUED; + atomic_dec(&q->owned_by_drv_count); + } vb2_v4l2 = to_vb2_v4l2_buffer(q->bufs[i]); - buf_info = container_of(vb2_v4l2, struct aml_video_dec_buf, vb); - - if (ctx->has_receive_eos) - buf_info->used = false; + buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb); + buf->frame_buffer.status = FB_ST_FREE; } } @@ -1475,36 +1614,31 @@ static void m2mops_vdec_device_run(void *priv) struct aml_vcodec_ctx *ctx = priv; struct aml_vcodec_dev *dev = ctx->dev; - aml_v4l2_debug(4,"%s() [%d]\n", __FUNCTION__, __LINE__); + aml_v4l2_debug(4, "[%d] %s() [%d]", ctx->id, __func__, __LINE__); queue_work(dev->decode_workqueue, &ctx->decode_work); } void vdec_device_vf_run(struct aml_vcodec_ctx *ctx) { - struct aml_vcodec_dev *dev = ctx->dev; + aml_v4l2_debug(3, "[%d] %s() [%d]", ctx->id, __func__, __LINE__); - aml_v4l2_debug(4,"%s() [%d]\n", __FUNCTION__, __LINE__); + if (ctx->state < AML_STATE_ACTIVE || + ctx->state > AML_STATE_FLUSHED) + return; - /*wake_up_interruptible(&ctx->wq);*/ - - queue_work(dev->decode_workqueue_vf, &ctx->decode_work_vf); + aml_thread_notify(ctx, AML_THREAD_CAPTURE); } static int m2mops_vdec_job_ready(void *m2m_priv) { struct aml_vcodec_ctx *ctx = m2m_priv; - aml_v4l2_debug(4, "[%d]", ctx->id); + aml_v4l2_debug(4, "[%d] %s(), state: %d", ctx->id, + __func__, ctx->state); - if (ctx->state == AML_STATE_ABORT) - return 0; - - if ((ctx->last_decoded_picinfo.pic_w != ctx->picinfo.pic_w) || - (ctx->last_decoded_picinfo.pic_h != ctx->picinfo.pic_h)) - return 0; - - if (ctx->state != AML_STATE_HEADER) + if (ctx->state < AML_STATE_PROBE || + ctx->state > AML_STATE_FLUSHED) return 0; return 1; @@ -1514,9 +1648,13 @@ static void m2mops_vdec_job_abort(void *priv) { struct aml_vcodec_ctx *ctx = priv; - aml_v4l2_debug(1, "%s() [%d]\n", __FUNCTION__, __LINE__); + aml_v4l2_debug(3, "[%d] %s() [%d]", ctx->id, __func__, __LINE__); ctx->state = AML_STATE_ABORT; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ABORT)", + ctx->id, __func__); + + wake_up(&ctx->m2m_ctx->finished); } static int aml_vdec_g_v_ctrl(struct v4l2_ctrl *ctrl) @@ -1524,14 +1662,14 @@ static int aml_vdec_g_v_ctrl(struct v4l2_ctrl *ctrl) struct aml_vcodec_ctx *ctx = ctrl_to_ctx(ctrl); int ret = 0; - aml_v4l2_debug(4,"%s() [%d]\n", __FUNCTION__, __LINE__); + aml_v4l2_debug(4, "%s() [%d]", __func__, __LINE__); switch (ctrl->id) { case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: - if (ctx->state >= AML_STATE_HEADER) { + if (ctx->state >= AML_STATE_PROBE) { ctrl->val = ctx->dpb_size; } else { - aml_v4l2_debug(0, "Seqinfo not ready"); + pr_err("Seqinfo not ready.\n"); ctrl->val = 0; } break; @@ -1558,8 +1696,8 @@ int aml_vcodec_dec_ctrls_setup(struct aml_vcodec_ctx *ctx) ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; if (ctx->ctrl_hdl.error) { - aml_v4l2_err("Adding control failed %d", - ctx->ctrl_hdl.error); + aml_v4l2_err("[%d] Adding control failed %d", + ctx->id, ctx->ctrl_hdl.error); return ctx->ctrl_hdl.error; } @@ -1571,7 +1709,7 @@ static void m2mops_vdec_lock(void *m2m_priv) { struct aml_vcodec_ctx *ctx = m2m_priv; - aml_v4l2_debug(4, "[%d]", ctx->id); + aml_v4l2_debug(4, "[%d] %s()", ctx->id, __func__); mutex_lock(&ctx->dev->dev_mutex); } @@ -1579,7 +1717,7 @@ static void m2mops_vdec_unlock(void *m2m_priv) { struct aml_vcodec_ctx *ctx = m2m_priv; - aml_v4l2_debug(4, "[%d]", ctx->id); + aml_v4l2_debug(4, "[%d] %s()", ctx->id, __func__); mutex_unlock(&ctx->dev->dev_mutex); } @@ -1644,7 +1782,7 @@ int aml_vcodec_dec_queue_init(void *priv, struct vb2_queue *src_vq, struct aml_vcodec_ctx *ctx = priv; int ret = 0; - aml_v4l2_debug(4, "[%d]", ctx->id); + aml_v4l2_debug(4, "[%d] %s()", ctx->id, __func__); src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; src_vq->io_modes = VB2_DMABUF | VB2_MMAP; @@ -1657,11 +1795,11 @@ int aml_vcodec_dec_queue_init(void *priv, struct vb2_queue *src_vq, ret = vb2_queue_init(src_vq); if (ret) { - aml_v4l2_err("Failed to initialize videobuf2 queue(output)"); + aml_v4l2_err("[%d] Failed to initialize videobuf2 queue(output)", ctx->id); return ret; } dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - dst_vq->io_modes = VB2_DMABUF | VB2_MMAP; + dst_vq->io_modes = VB2_DMABUF | VB2_MMAP | VB2_USERPTR; dst_vq->drv_priv = ctx; dst_vq->buf_struct_size = sizeof(struct aml_video_dec_buf); dst_vq->ops = &aml_vdec_vb2_ops; @@ -1672,7 +1810,7 @@ int aml_vcodec_dec_queue_init(void *priv, struct vb2_queue *src_vq, ret = vb2_queue_init(dst_vq); if (ret) { vb2_queue_release(src_vq); - aml_v4l2_err("Failed to initialize videobuf2 queue(capture)"); + aml_v4l2_err("[%d] Failed to initialize videobuf2 queue(capture)", ctx->id); } return ret; diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec.h b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec.h index ae9f1e9338fa..62ef2c91d467 100644 --- a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec.h +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec.h @@ -49,8 +49,11 @@ struct aml_video_dec_buf { struct vdec_fb frame_buffer; struct codec_mm_s *mem[2]; + char mem_onwer[32]; + struct list_head node; bool used; bool ready_to_display; + bool que_in_m2m; bool queued_in_vb2; bool queued_in_v4l2; bool lastframe; @@ -77,4 +80,11 @@ 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); +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); + #endif /* _AML_VCODEC_DEC_H_ */ diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_drv.c b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_drv.c index f931c602bb48..8a45a032d05b 100644 --- a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_drv.c +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_drv.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "aml_vcodec_drv.h" #include "aml_vcodec_dec.h" @@ -49,24 +50,26 @@ 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; init_waitqueue_head(&ctx->queue); + mutex_init(&ctx->state_lock); mutex_init(&ctx->lock); - sema_init(&ctx->sem, 1); init_waitqueue_head(&ctx->wq); ctx->type = AML_INST_DECODER; ret = aml_vcodec_dec_ctrls_setup(ctx); if (ret) { - aml_v4l2_err("Failed to setup mt vcodec controls\n"); + aml_v4l2_err("Failed to setup vcodec controls"); goto err_ctrls_setup; } ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev_dec, ctx, &aml_vcodec_dec_queue_init); if (IS_ERR((__force void *)ctx->m2m_ctx)) { ret = PTR_ERR((__force void *)ctx->m2m_ctx); - aml_v4l2_err("Failed to v4l2_m2m_ctx_init() (%d)\n", ret); + aml_v4l2_err("Failed to v4l2_m2m_ctx_init() (%d)", ret); goto err_m2m_ctx_init; } src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, @@ -75,6 +78,12 @@ static int fops_vcodec_open(struct file *file) ctx->empty_flush_buf->lastframe = true; aml_vcodec_dec_set_default_params(ctx); + ret = aml_thread_start(ctx, try_to_capture, AML_THREAD_CAPTURE, "cap"); + if (ret) { + aml_v4l2_err("Failed to creat capture thread."); + goto err_creat_thread; + } + list_add(&ctx->list, &dev->ctx_list); mutex_unlock(&dev->dev_mutex); @@ -83,8 +92,8 @@ static int fops_vcodec_open(struct file *file) return ret; /* Deinit when failure occurred */ -//err_load_fw: - /*v4l2_m2m_ctx_release(ctx->m2m_ctx);*/ +err_creat_thread: + v4l2_m2m_ctx_release(ctx->m2m_ctx); err_m2m_ctx_init: v4l2_ctrl_handler_free(&ctx->ctrl_hdl); err_ctrls_setup: @@ -111,13 +120,15 @@ static int fops_vcodec_release(struct file *file) * Second, the decoder will be flushed and all the buffers will be * returned in stop_streaming. */ - v4l2_m2m_ctx_release(ctx->m2m_ctx); aml_vcodec_dec_release(ctx); + v4l2_m2m_ctx_release(ctx->m2m_ctx); v4l2_fh_del(&ctx->fh); v4l2_fh_exit(&ctx->fh); v4l2_ctrl_handler_free(&ctx->ctrl_hdl); + aml_thread_stop(ctx); + list_del_init(&ctx->list); kfree(ctx->empty_flush_buf); kfree(ctx); @@ -156,7 +167,7 @@ static int aml_vcodec_probe(struct platform_device *pdev) ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); if (ret) { - aml_v4l2_err("v4l2_device_register err=%d\n", ret); + aml_v4l2_err("v4l2_device_register err=%d", ret); goto err_res; } @@ -164,7 +175,7 @@ static int aml_vcodec_probe(struct platform_device *pdev) vfd_dec = video_device_alloc(); if (!vfd_dec) { - aml_v4l2_err("Failed to allocate video device\n"); + aml_v4l2_err("Failed to allocate video device"); ret = -ENOMEM; goto err_dec_alloc; } @@ -186,7 +197,7 @@ static int aml_vcodec_probe(struct platform_device *pdev) dev->m2m_dev_dec = v4l2_m2m_init(&aml_vdec_m2m_ops); if (IS_ERR((__force void *)dev->m2m_dev_dec)) { - aml_v4l2_err("Failed to init mem2mem dec device\n"); + aml_v4l2_err("Failed to init mem2mem dec device"); ret = PTR_ERR((__force void *)dev->m2m_dev_dec); goto err_dec_mem_init; } @@ -195,28 +206,17 @@ static int aml_vcodec_probe(struct platform_device *pdev) alloc_ordered_workqueue(AML_VCODEC_DEC_NAME, WQ_MEM_RECLAIM | WQ_FREEZABLE); if (!dev->decode_workqueue) { - aml_v4l2_err("Failed to create decode workqueue\n"); + aml_v4l2_err("Failed to create decode workqueue"); ret = -EINVAL; goto err_event_workq; } - dev->decode_workqueue_vf = - alloc_ordered_workqueue("aml-vcodec-dec-vf", - WQ_MEM_RECLAIM | WQ_FREEZABLE); - if (!dev->decode_workqueue_vf) { - aml_v4l2_err("Failed to create decode workqueue\n"); - ret = -EINVAL; - destroy_workqueue(dev->decode_workqueue); - goto err_event_workq; - } - dev->reset_workqueue = alloc_ordered_workqueue("aml-vcodec-reset", WQ_MEM_RECLAIM | WQ_FREEZABLE); - if (!dev->decode_workqueue_vf) { - aml_v4l2_err("Failed to create decode workqueue\n"); + if (!dev->reset_workqueue) { + aml_v4l2_err("Failed to create decode workqueue"); ret = -EINVAL; - destroy_workqueue(dev->decode_workqueue_vf); destroy_workqueue(dev->decode_workqueue); goto err_event_workq; } @@ -235,7 +235,6 @@ static int aml_vcodec_probe(struct platform_device *pdev) err_dec_reg: destroy_workqueue(dev->reset_workqueue); - destroy_workqueue(dev->decode_workqueue_vf); destroy_workqueue(dev->decode_workqueue); err_event_workq: v4l2_m2m_release(dev->m2m_dev_dec); @@ -259,8 +258,8 @@ static int aml_vcodec_dec_remove(struct platform_device *pdev) { struct aml_vcodec_dev *dev = platform_get_drvdata(pdev); - flush_workqueue(dev->decode_workqueue_vf); - destroy_workqueue(dev->decode_workqueue_vf); + flush_workqueue(dev->reset_workqueue); + destroy_workqueue(dev->reset_workqueue); flush_workqueue(dev->decode_workqueue); destroy_workqueue(dev->decode_workqueue); diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_drv.h b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_drv.h index 4b9573091c84..4e00b233de17 100644 --- a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_drv.h +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_drv.h @@ -12,7 +12,7 @@ #define AML_VCODEC_DRV_NAME "aml_vcodec_drv" #define AML_VCODEC_DEC_NAME "aml-vcodec-dec" #define AML_VCODEC_ENC_NAME "aml-vcodec-enc" -#define AML_PLATFORM_STR "platform:mt8173" +#define AML_PLATFORM_STR "platform:amlogic" #define AML_VCODEC_MAX_PLANES 3 #define AML_V4L2_BENCHMARK 0 @@ -52,20 +52,25 @@ enum aml_instance_type { /** * enum aml_instance_state - The state of an AML Vcodec instance. - * @AML_STATE_FREE - default state when instance is created - * @AML_STATE_INIT - vcodec instance is initialized - * @AML_STATE_HEADER - vdec had sps/pps header parsed or venc - * had sps/pps header encoded - * @AML_STATE_FLUSH - vdec is flushing. Only used by decoder - * @AML_STATE_ABORT - vcodec should be aborted + * @AML_STATE_IDLE - default state when instance is created + * @AML_STATE_INIT - vcodec instance is initialized + * @AML_STATE_PROBE - vdec/venc had sps/pps header parsed/encoded + * @AML_STATE_ACTIVE - vdec is ready for work. + * @AML_STATE_FLUSHING - vdec is flushing. Only used by decoder + * @AML_STATE_FLUSHED - decoder has transacted the last frame. + * @AML_STATE_RESET - decoder has be reset after flush. + * @AML_STATE_ABORT - vcodec should be aborted */ enum aml_instance_state { - AML_STATE_FREE = 0, - AML_STATE_INIT = 1, - AML_STATE_HEADER = 2, - AML_STATE_FLUSH = 3, - AML_STATE_ABORT = 4, - AML_STATE_RESET = 5, + AML_STATE_IDLE, + AML_STATE_INIT, + AML_STATE_PROBE, + AML_STATE_READY, + AML_STATE_ACTIVE, + AML_STATE_FLUSHING, + AML_STATE_FLUSHED, + AML_STATE_RESET, + AML_STATE_ABORT, }; /** @@ -186,10 +191,10 @@ struct aml_vcodec_pm { /** * struct vdec_pic_info - picture size information - * @pic_w: picture width - * @pic_h: picture height - * @buf_w: picture buffer width (64 aligned up from pic_w) - * @buf_h: picture buffer heiht (64 aligned up from pic_h) + * @visible_width: picture width + * @visible_height: picture height + * @coded_width: picture buffer width (64 aligned up from pic_w) + * @coded_height: picture buffer heiht (64 aligned up from pic_h) * @y_bs_sz: Y bitstream size * @c_bs_sz: CbCr bitstream size * @y_len_sz: additional size required to store decompress information for y @@ -200,16 +205,35 @@ struct aml_vcodec_pm { * buffer size will be aligned to 176x160. */ struct vdec_pic_info { - unsigned int pic_w; - unsigned int pic_h; - unsigned int buf_w; - unsigned int buf_h; + unsigned int visible_width; + unsigned int visible_height; + unsigned int coded_width; + unsigned int coded_height; unsigned int y_bs_sz; unsigned int c_bs_sz; unsigned int y_len_sz; unsigned int c_len_sz; }; +enum aml_thread_type { + AML_THREAD_OUTPUT, + AML_THREAD_CAPTURE, +}; + +typedef void (*aml_thread_func)(struct aml_vcodec_ctx *ctx); + +struct aml_vdec_thread { + struct list_head node; + spinlock_t lock; + struct semaphore sem; + struct task_struct *task; + enum aml_thread_type type; + void *priv; + int stop; + + aml_thread_func func; +}; + /** * struct aml_vcodec_ctx - Context (instance) private data. * @@ -256,8 +280,10 @@ struct aml_vcodec_ctx { struct v4l2_fh fh; struct v4l2_m2m_ctx *m2m_ctx; + struct aml_vdec_adapt *ada_ctx; struct aml_q_data q_data[2]; int id; + struct mutex state_lock; enum aml_instance_state state; enum aml_encode_param param_change; struct aml_enc_params enc_params; @@ -276,7 +302,6 @@ struct aml_vcodec_ctx { struct v4l2_ctrl_handler ctrl_hdl; struct work_struct decode_work; - struct work_struct decode_work_vf; struct work_struct encode_work; struct work_struct reset_work; struct vdec_pic_info last_decoded_picinfo; @@ -289,10 +314,10 @@ struct aml_vcodec_ctx { int decoded_frame_cnt; struct mutex lock; - struct semaphore sem; wait_queue_head_t wq; bool has_receive_eos; - + struct list_head capture_list; + struct list_head vdec_thread_list; }; /** @@ -352,7 +377,6 @@ struct aml_vcodec_dev { unsigned long id_counter; struct workqueue_struct *decode_workqueue; - struct workqueue_struct *decode_workqueue_vf; struct workqueue_struct *encode_workqueue; struct workqueue_struct *reset_workqueue; int int_cond; diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_util.c b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_util.c index b30dd2b051ea..32733e35012f 100644 --- a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_util.c +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_util.c @@ -45,10 +45,10 @@ int aml_vcodec_mem_alloc(struct aml_vcodec_ctx *data, memset(mem->va, 0, size); - aml_v4l2_debug(3, "[%d] - va = %p", ctx->id, mem->va); - aml_v4l2_debug(3, "[%d] - dma = 0x%lx", ctx->id, + aml_v4l2_debug(4, "[%d] - va = %p", ctx->id, mem->va); + aml_v4l2_debug(4, "[%d] - dma = 0x%lx", ctx->id, (unsigned long)mem->dma_addr); - aml_v4l2_debug(3, "[%d] size = 0x%lx", ctx->id, size); + aml_v4l2_debug(4, "[%d] size = 0x%lx", ctx->id, size); return 0; } @@ -67,10 +67,10 @@ void aml_vcodec_mem_free(struct aml_vcodec_ctx *data, return; } - aml_v4l2_debug(3, "[%d] - va = %p", ctx->id, mem->va); - aml_v4l2_debug(3, "[%d] - dma = 0x%lx", ctx->id, + aml_v4l2_debug(4, "[%d] - va = %p", ctx->id, mem->va); + aml_v4l2_debug(4, "[%d] - dma = 0x%lx", ctx->id, (unsigned long)mem->dma_addr); - aml_v4l2_debug(3, "[%d] size = 0x%lx", ctx->id, size); + aml_v4l2_debug(4, "[%d] size = 0x%lx", ctx->id, size); dma_free_coherent(dev, size, mem->va, mem->dma_addr); mem->va = NULL; diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_util.h b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_util.h index 861c8e6a0286..ee9b5370116a 100644 --- a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_util.h +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_util.h @@ -23,11 +23,10 @@ extern bool aml_vcodec_dbg; #if defined(DEBUG) -#define aml_v4l2_debug(level, fmt, args...) \ - do { \ - if (aml_v4l2_dbg_level >= level) \ - pr_info("[AML_V4L2] level=%d %s(),%d: " fmt "\n",\ - level, __func__, __LINE__, ##args); \ +#define aml_v4l2_debug(level, fmt, args...) \ + do { \ + if (aml_v4l2_dbg_level >= level) \ + pr_info(fmt "\n", ##args); \ } while (0) #define aml_v4l2_debug_enter() aml_v4l2_debug(3, "+") @@ -36,8 +35,8 @@ extern bool aml_vcodec_dbg; #define aml_vcodec_debug(h, fmt, args...) \ do { \ if (aml_vcodec_dbg) \ - pr_info("[AML_VCODEC][%d]: %s() " fmt "\n", \ - ((struct aml_vcodec_ctx *)h->ctx)->id, \ + pr_info("[%d]: %s() " fmt "\n", \ + ((struct aml_vcodec_ctx *)h->ctx)->id, \ __func__, ##args); \ } while (0) @@ -56,13 +55,12 @@ extern bool aml_vcodec_dbg; #endif -#define aml_v4l2_err(fmt, args...) \ - pr_err("[AML_V4L2][ERROR] %s:%d: " fmt "\n", __func__, __LINE__, \ - ##args) +#define aml_v4l2_err(fmt, args...) \ + pr_err("[ERR]" fmt "\n", ##args) #define aml_vcodec_err(h, fmt, args...) \ - pr_err("[AML_VCODEC][ERROR][%d]: %s() " fmt "\n", \ - ((struct aml_vcodec_ctx *)h->ctx)->id, __func__, ##args) + pr_err("[ERR][%d]" fmt "\n", \ + ((struct aml_vcodec_ctx *)h->ctx)->id, ##args) void __iomem *aml_vcodec_get_reg_addr(struct aml_vcodec_ctx *data, unsigned int reg_idx); diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfm.c b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfm.c index 0ee4be4d3f75..307b18fc21da 100644 --- a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfm.c +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfm.c @@ -1,6 +1,7 @@ #include "aml_vcodec_vfm.h" #include "aml_vcodec_vfq.h" #include "aml_vcodec_util.h" +#include "aml_vcodec_adapt.h" #include #define RECEIVER_NAME "v4l2-video" @@ -50,16 +51,16 @@ static int vdec_vf_states(struct vframe_states *states, void *op_arg) return 0; } -void video_vf_put(struct vdec_fb *fb) +void video_vf_put(char *receiver, struct vdec_fb *fb, int id) { - struct vframe_provider_s *vfp = vf_get_provider(RECEIVER_NAME); + struct vframe_provider_s *vfp = vf_get_provider(receiver); struct vframe_s *vf = (struct vframe_s *)fb->vf_handle; - aml_v4l2_debug(4, "%s() [%d], vfp: %p, vf: %p, cnt: %d\n", - __FUNCTION__, __LINE__, vfp, vf, atomic_read(&vf->use_cnt)); + aml_v4l2_debug(2, "[%d] TO (%s) vf: %p, idx: %d", + id, vfp->name, vf, vf->index); if (vfp && vf && atomic_dec_and_test(&vf->use_cnt)) - vf_put(vf, RECEIVER_NAME); + vf_put(vf, receiver); } static const struct vframe_operations_s vf_provider = { @@ -76,26 +77,23 @@ static int video_receiver_event_fun(int type, void *data, void *private_data) struct vframe_states states; struct vcodec_vfm_s *vfm = (struct vcodec_vfm_s *)private_data; - aml_v4l2_debug(4, "%s() [%d], type: %d, vfm: %p\n", - __FUNCTION__, __LINE__, type, vfm); + //aml_v4l2_debug(4, "[%d] type: %d, vfm: %p", vfm->ctx->id, type, vfm); switch (type) { case VFRAME_EVENT_PROVIDER_UNREG: { if (vf_get_receiver(vfm->prov_name)) { - aml_v4l2_debug(4, "%s() [%d] unreg %s provider.\n", - __FUNCTION__, __LINE__, vfm->prov_name); + aml_v4l2_debug(4, "[%d] unreg %s provider.", + vfm->ctx->id, vfm->prov_name); vf_unreg_provider(&vfm->vf_prov); } - vfq_init(&vfm->vf_que, POOL_SIZE + 1, &vfm->pool[0]); - break; } case VFRAME_EVENT_PROVIDER_START: { if (vf_get_receiver(vfm->prov_name)) { - aml_v4l2_debug(4, "%s() [%d] reg %s provider.\n", - __FUNCTION__, __LINE__, vfm->prov_name); + aml_v4l2_debug(4, "[%d] reg %s provider.", + vfm->ctx->id, vfm->prov_name); vf_provider_init(&vfm->vf_prov, vfm->prov_name, &vf_provider, vfm); vf_reg_provider(&vfm->vf_prov); @@ -126,6 +124,11 @@ static int video_receiver_event_fun(int type, void *data, void *private_data) if (!vfm->vf) ret = -1; + if (ret < 0) { + pr_err("[%d] receiver vf err.\n", vfm->ctx->id); + break; + } + vfq_push(&vfm->vf_que, vfm->vf); /*vf_notify_receiver(vfm->prov_name, @@ -133,14 +136,15 @@ static int video_receiver_event_fun(int type, void *data, void *private_data) /* schedule capture work. */ vdec_device_vf_run(vfm->ctx); - aml_v4l2_debug(1, "%s() [%d] VFRAME_EVENT_PROVIDER_VFRAME_READY.\n", - __FUNCTION__, __LINE__); + aml_v4l2_debug(2, "[%d] FROM (%s) vf: %p, idx: %d", + vfm->ctx->id, vf_get_provider(vfm->recv_name)->name, + vfm->vf, vfm->vf->index); break; } default: - aml_v4l2_debug(4, "the vf event is %d .", type); + aml_v4l2_debug(4, "[%d] the vf event is %d", vfm->ctx->id, type); } return ret; @@ -162,8 +166,12 @@ struct vframe_s *get_video_frame(struct vcodec_vfm_s *vfm) int vcodec_vfm_init(struct vcodec_vfm_s *vfm) { - memcpy(vfm->recv_name, RECEIVER_NAME, sizeof(RECEIVER_NAME)); - memcpy(vfm->prov_name, PROVIDER_NAME, sizeof(PROVIDER_NAME)); + snprintf(vfm->recv_name, VF_NAME_SIZE, "%s-%d", + RECEIVER_NAME, vfm->ctx->id); + snprintf(vfm->prov_name, VF_NAME_SIZE, "%s-%d", + PROVIDER_NAME, vfm->ctx->id); + + 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); @@ -174,6 +182,5 @@ int vcodec_vfm_init(struct vcodec_vfm_s *vfm) void vcodec_vfm_release(struct vcodec_vfm_s *vfm) { vf_unreg_receiver(&vfm->vf_recv); - vf_unreg_provider(&vfm->vf_prov); } diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfm.h b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfm.h index a47916c36aea..268e8eb07cc5 100644 --- a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfm.h +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfm.h @@ -8,10 +8,11 @@ #include #define VF_NAME_SIZE (32) -#define POOL_SIZE (16) +#define POOL_SIZE (64) struct vcodec_vfm_s { struct aml_vcodec_ctx *ctx; + struct aml_vdec_adapt *ada_ctx; struct vfq_s vf_que; struct vframe_s *vf; struct vframe_s *pool[POOL_SIZE + 1]; @@ -32,6 +33,6 @@ struct vframe_s *get_video_frame(struct vcodec_vfm_s *vfm); int get_fb_from_queue(struct aml_vcodec_ctx *ctx, struct vdec_fb **out_fb); int put_fb_to_queue(struct aml_vcodec_ctx *ctx, struct vdec_fb *in_fb); -void video_vf_put(struct vdec_fb *fb); +void video_vf_put(char *receiver, struct vdec_fb *fb, int id); #endif /* __AML_VCODEC_VFM_H_ */ diff --git a/drivers/amlogic/media_modules/amvdec_ports/decoder/vdec_h264_if.c b/drivers/amlogic/media_modules/amvdec_ports/decoder/vdec_h264_if.c index fbda1f298715..2e414f2b2770 100644 --- a/drivers/amlogic/media_modules/amvdec_ports/decoder/vdec_h264_if.c +++ b/drivers/amlogic/media_modules/amvdec_ports/decoder/vdec_h264_if.c @@ -12,6 +12,7 @@ #include "../aml_vcodec_vfm.h" #include "h264_stream.h" #include "h264_parse.h" +#include /* h264 NALU type */ #define NAL_NON_IDR_SLICE 0x01 @@ -32,6 +33,8 @@ #define H264_MAX_FB_NUM 17 #define HDR_PARSING_BUF_SZ 1024 +#define HEADER_BUFFER_SIZE (32 * 1024) + /** * struct h264_fb - h264 decode frame buffer information * @vdec_fb_va : virtual address of struct vdec_fb @@ -104,6 +107,7 @@ struct vdec_h264_dec_info { */ struct vdec_h264_vsi { unsigned char hdr_buf[HDR_PARSING_BUF_SZ]; + char *header_buf; int sps_size; int pps_size; int sei_size; @@ -137,8 +141,6 @@ struct vdec_h264_inst { struct vcodec_vfm_s vfm; }; -static DEFINE_MUTEX(mutex); - #define DUMP_FILE_NAME "/data/dump/dump.tmp" static struct file *filp; static loff_t file_pos; @@ -177,13 +179,25 @@ void dump_deinit(void) } } +void swap_uv(void *uv, int size) +{ + int i; + __u16 *p = uv; + + size /= 2; + + for (i = 0; i < size; i++, p++) + *p = __swab16(*p); +} + static void get_pic_info(struct vdec_h264_inst *inst, struct vdec_pic_info *pic) { *pic = inst->vsi->pic; aml_vcodec_debug(inst, "pic(%d, %d), buf(%d, %d)", - pic->pic_w, pic->pic_h, pic->buf_w, pic->buf_h); + pic->visible_width, pic->visible_height, + pic->coded_width, pic->coded_height); aml_vcodec_debug(inst, "Y(%d, %d), C(%d, %d)", pic->y_bs_sz, pic->y_len_sz, pic->c_bs_sz, pic->c_len_sz); } @@ -220,7 +234,7 @@ static int find_start_code(unsigned char *data, unsigned int data_sz) static int vdec_h264_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) { struct vdec_h264_inst *inst = NULL; - int err = -1; + int ret = -1; inst = kzalloc(sizeof(*inst), GFP_KERNEL); if (!inst) @@ -228,56 +242,60 @@ static int vdec_h264_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) inst->ctx = ctx; - inst->vdec.id = VFORMAT_H264; + inst->vdec.format = VFORMAT_H264; inst->vdec.dev = ctx->dev->vpu_plat_dev; inst->vdec.filp = ctx->dev->filp; inst->vdec.ctx = ctx; inst->vfm.ctx = ctx; + inst->vfm.ada_ctx = &inst->vdec; vcodec_vfm_init(&inst->vfm); - //inst->vpu.handler = vpu_dec_ipi_handler; - - err = video_decoder_init(&inst->vdec); - if (err) { - aml_vcodec_err(inst, "vdec_h264 init err=%d", err); - //goto error_free_inst; + ret = video_decoder_init(&inst->vdec); + if (ret) { + aml_vcodec_err(inst, "vdec_h264 init err=%d", ret); + goto error_free_inst; } - //inst->vsi = (struct vdec_h264_vsi *)inst->vpu.vsi; - - //probe info from the decoder hw debug_tmp + /* probe info from the stream */ inst->vsi = kzalloc(sizeof(struct vdec_h264_vsi), GFP_KERNEL); + if (!inst->vsi) { + ret = -ENOMEM; + goto error_free_inst; + } - //debug_tmp - inst->vsi->pic.pic_w = 1920; - inst->vsi->pic.pic_h = 1088; - inst->vsi->pic.buf_w = 1920; - inst->vsi->pic.buf_h = 1088; + /* 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; + } + + 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); - //err = allocate_predication_buf(inst); - //if (err) - //goto error_deinit; - aml_vcodec_debug(inst, "H264 Instance >> %p", inst); + ctx->ada_ctx = &inst->vdec; *h_vdec = (unsigned long)inst; dump_init(); return 0; -//error_deinit: - //vpu_dec_deinit(&inst->vpu); - -//error_free_inst: - /*kfree(inst->vsi); +error_free_vsi: + kfree(inst->vsi); +error_free_inst: kfree(inst); - return err;*/ + *h_vdec = 0; + + return ret; } static int refer_buffer_num(int level_idc, int poc_cnt, @@ -352,11 +370,11 @@ static int refer_buffer_num(int level_idc, int poc_cnt, return size; } -static void fill_vdec_params(struct h264_SPS_t *sps, struct vdec_h264_vsi *vsi) +static void fill_vdec_params(struct vdec_h264_inst *inst, struct h264_SPS_t *sps) { - struct vdec_pic_info *pic = &vsi->pic; - struct vdec_h264_dec_info *dec = &vsi->dec; - struct v4l2_rect *rect = &vsi->crop; + struct vdec_pic_info *pic = &inst->vsi->pic; + struct vdec_h264_dec_info *dec = &inst->vsi->dec; + struct v4l2_rect *rect = &inst->vsi->crop; unsigned int mb_w, mb_h, width, height; unsigned int crop_unit_x = 0, crop_unit_y = 0; unsigned int poc_cnt = 0; @@ -388,21 +406,21 @@ static void fill_vdec_params(struct h264_SPS_t *sps, struct vdec_h264_vsi *vsi) height -= crop_unit_y * (sps->frame_crop_top_offset + sps->frame_crop_bottom_offset); - /* fill image size that be used for EGL. */ - pic->pic_w = width; - pic->pic_h = height; + /* fill visible area size that be used for EGL. */ + pic->visible_width = width; + pic->visible_height = height; /* calc visible ares. */ - rect->left = 0; - rect->top = 0; - rect->width = pic->pic_w; - rect->height = pic->pic_h; + rect->left = 0; + rect->top = 0; + rect->width = pic->visible_width; + rect->height = pic->visible_height; /* config canvas size that be used for decoder. */ - pic->buf_w = ALIGN(mb_w, 4) << 4; - pic->buf_h = ALIGN(mb_h, 4) << 4; - pic->y_len_sz = pic->buf_w * pic->buf_h; - pic->c_len_sz = pic->y_len_sz >> 1; + pic->coded_width = ALIGN(mb_w, 4) << 4; + 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; /* calc DPB size */ poc_cnt = sps->pic_order_cnt_type; @@ -411,8 +429,9 @@ static void fill_vdec_params(struct h264_SPS_t *sps, struct vdec_h264_vsi *vsi) dec->dpb_sz = refer_buffer_num(sps->level_idc, poc_cnt, mb_w, mb_h); - pr_info("the stream infos, width: %d, height: %d, dpb: %d\n", - pic->pic_w, pic->pic_h, dec->dpb_sz); + 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); } static int vdec_h264_probe(unsigned long h_vdec, @@ -448,7 +467,7 @@ static int vdec_h264_probe(unsigned long h_vdec, h264_sps_parse(&s, sps); //h264_sps_info(sps); - fill_vdec_params(sps, inst->vsi); + fill_vdec_params(inst, sps); kfree(sps); @@ -459,7 +478,8 @@ static void vdec_h264_deinit(unsigned long h_vdec) { struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec; - mutex_lock(&mutex); + if (!inst) + return; aml_vcodec_debug_enter(inst); @@ -469,11 +489,13 @@ static void vdec_h264_deinit(unsigned long h_vdec) dump_deinit(); - kfree(inst->vsi); - kfree(inst); - inst = NULL; + if (inst->vsi && inst->vsi->header_buf) + kfree(inst->vsi->header_buf); - mutex_unlock(&mutex); + if (inst->vsi) + kfree(inst->vsi); + + kfree(inst); } static int vdec_h264_get_fb(struct vdec_h264_inst *inst, struct vdec_fb **out) @@ -486,27 +508,27 @@ static void vdec_h264_get_vf(struct vdec_h264_inst *inst, struct vdec_fb **out) struct vframe_s *vf = NULL; struct vdec_fb *fb = NULL; - aml_vcodec_debug(inst, "%s() [%d], vfm: %p\n", - __FUNCTION__, __LINE__, &inst->vfm); + aml_vcodec_debug(inst, "%s() [%d], vfm: %p", + __func__, __LINE__, &inst->vfm); vf = peek_video_frame(&inst->vfm); if (!vf) { - aml_vcodec_debug(inst, "there is no vframe.\n"); + aml_vcodec_debug(inst, "there is no vframe."); *out = NULL; return; } vf = get_video_frame(&inst->vfm); if (!vf) { - aml_vcodec_debug(inst, "the vframe is avalid.\n"); + aml_vcodec_debug(inst, "the vframe is avalid."); *out = NULL; return; } atomic_set(&vf->use_cnt, 1); - aml_vcodec_debug(inst, "%s() [%d], vf: %p, v4l_mem_handle: %lx\n", - __FUNCTION__, __LINE__, vf, vf->v4l_mem_handle); + aml_vcodec_debug(inst, "%s() [%d], vf: %p, v4l_mem_handle: %lx, idx: %d\n", + __func__, __LINE__, vf, vf->v4l_mem_handle, vf->index); fb = (struct vdec_fb *)vf->v4l_mem_handle; fb->vf_handle = (unsigned long)vf; @@ -514,14 +536,18 @@ static void vdec_h264_get_vf(struct vdec_h264_inst *inst, struct vdec_fb **out) *out = fb; + //pr_info("%s, %d\n", __func__, fb->base_y.bytes_used); //dump_write(fb->base_y.va, fb->base_y.bytes_used); //dump_write(fb->base_c.va, fb->base_c.bytes_used); - aml_vcodec_debug(inst, "%s() [%d], va: %p, phy: %x, size: %zu\n", - __FUNCTION__, __LINE__, fb->base_y.va, + /* convert yuv format. */ + //swap_uv(fb->base_c.va, fb->base_c.size); + + aml_vcodec_debug(inst, "%s() [%d], va: %p, phy: %x, size: %lu", + __func__, __LINE__, fb->base_y.va, (unsigned int)virt_to_phys(fb->base_y.va), fb->base_y.size); - aml_vcodec_debug(inst, "%s() [%d], va: %p, phy: %x, size: %zu\n", - __FUNCTION__, __LINE__, fb->base_c.va, + aml_vcodec_debug(inst, "%s() [%d], va: %p, phy: %x, size: %lu", + __func__, __LINE__, fb->base_c.va, (unsigned int)virt_to_phys(fb->base_c.va), fb->base_c.size); } @@ -550,47 +576,46 @@ static int vdec_h264_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs, nal_start = buf[nal_start_idx]; nal_type = NAL_TYPE(buf[nal_start_idx]); - aml_v4l2_debug(1, "NALU type: %d, size: %u\n", nal_type, buf_sz); + aml_vcodec_debug(inst, "NALU type: %d, size: %u", nal_type, buf_sz); if (nal_type == NAL_H264_SPS) { - if (buf_sz > HDR_PARSING_BUF_SZ) { + if (inst->vsi->head_offset + buf_sz > HEADER_BUFFER_SIZE) { err = -EILSEQ; goto err_free_fb_out; } inst->vsi->sps_size = buf_sz; - memcpy(inst->vsi->hdr_buf + inst->vsi->head_offset, buf, buf_sz); + memcpy(inst->vsi->header_buf + inst->vsi->head_offset, buf, buf_sz); inst->vsi->head_offset += inst->vsi->sps_size; } else if (nal_type == NAL_H264_PPS) { //buf_sz -= nal_start_idx; - if (buf_sz > HDR_PARSING_BUF_SZ) { + if (inst->vsi->head_offset + buf_sz > HEADER_BUFFER_SIZE) { err = -EILSEQ; goto err_free_fb_out; } inst->vsi->pps_size = buf_sz; - memcpy(inst->vsi->hdr_buf + inst->vsi->head_offset, buf, buf_sz); + memcpy(inst->vsi->header_buf + inst->vsi->head_offset, buf, buf_sz); inst->vsi->head_offset += inst->vsi->pps_size; } else if (nal_type == NAL_H264_SEI) { - if (buf_sz > HDR_PARSING_BUF_SZ) { + if (inst->vsi->head_offset + buf_sz > HEADER_BUFFER_SIZE) { err = -EILSEQ; goto err_free_fb_out; } inst->vsi->sei_size = buf_sz; - memcpy(inst->vsi->hdr_buf + inst->vsi->head_offset, buf, buf_sz); + memcpy(inst->vsi->header_buf + inst->vsi->head_offset, buf, buf_sz); inst->vsi->head_offset += inst->vsi->sei_size; } else { char *write_buf = vmalloc(inst->vsi->head_offset + buf_sz); - memcpy(write_buf, inst->vsi->hdr_buf, inst->vsi->head_offset); + memcpy(write_buf, inst->vsi->header_buf, inst->vsi->head_offset); memcpy(write_buf + inst->vsi->head_offset, buf, buf_sz); - ret = vdec_vframe_write(vdec->filp, write_buf, + ret = vdec_vframe_write(vdec, write_buf, inst->vsi->head_offset + buf_sz, timestamp); - aml_vcodec_debug(inst, - "%s() [%d], buf: %p, buf size: %u, write to: %d\n", - __FUNCTION__, __LINE__, write_buf, - inst->vsi->head_offset + buf_sz, ret); + aml_vcodec_debug(inst, "buf: %p, buf size: %u, write to: %d", + write_buf, inst->vsi->head_offset + buf_sz, ret); + memset(inst->vsi->header_buf, 0, HEADER_BUFFER_SIZE); inst->vsi->head_offset = 0; inst->vsi->sps_size = 0; inst->vsi->pps_size = 0; @@ -626,14 +651,12 @@ static int vdec_h264_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs, //vpu_dec_end(vpu); } - - aml_vcodec_debug(inst, "\n - NALU[%d] type=%d -\n", inst->num_nalu, - nal_type); return ret; err_free_fb_out: //put_fb_to_free(inst, fb); - aml_vcodec_err(inst, "\n - NALU[%d] err=%d -\n", inst->num_nalu, err); + aml_vcodec_err(inst, "NALU[%d] err=%d", inst->num_nalu, err); + return err; } @@ -643,17 +666,13 @@ static int vdec_h264_get_param(unsigned long h_vdec, int ret = 0; struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec; - mutex_lock(&mutex); - if (!inst) { - pr_err("the h264 inst of dec is void.\n"); - mutex_unlock(&mutex); + pr_err("the h264 inst of dec is void."); return -1; } switch (type) { case GET_PARAM_DISP_FRAME_BUFFER: - //vdec_h264_get_fb(inst, &inst->vsi->list_disp, true, out); vdec_h264_get_vf(inst, out); break; @@ -675,11 +694,9 @@ static int vdec_h264_get_param(unsigned long h_vdec, default: aml_vcodec_err(inst, "invalid get parameter type=%d", type); - return -EINVAL; + ret = -EINVAL; } - mutex_unlock(&mutex); - return ret; } diff --git a/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_if.c b/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_if.c index d6ccb63331a3..2b05dc66084f 100644 --- a/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_if.c +++ b/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_if.c @@ -74,17 +74,17 @@ int vdec_if_decode(struct aml_vcodec_ctx *ctx, struct aml_vcodec_mem *bs, if (ctx->drv_handle == 0) return -EIO; - aml_vdec_lock(ctx); + //aml_vdec_lock(ctx); aml_vcodec_set_curr_ctx(ctx->dev, ctx); //aml_vcodec_dec_clock_on(&ctx->dev->pm);//debug_tmp - enable_irq(ctx->dev->dec_irq); + //enable_irq(ctx->dev->dec_irq); ret = ctx->dec_if->decode(ctx->drv_handle, bs, timestamp, res_chg); //disable_irq(ctx->dev->dec_irq); //aml_vcodec_dec_clock_off(&ctx->dev->pm); aml_vcodec_set_curr_ctx(ctx->dev, NULL); - aml_vdec_unlock(ctx); + //aml_vdec_unlock(ctx); return ret; } @@ -97,9 +97,9 @@ int vdec_if_get_param(struct aml_vcodec_ctx *ctx, if (ctx->drv_handle == 0) return -EIO; - aml_vdec_lock(ctx); + //aml_vdec_lock(ctx); ret = ctx->dec_if->get_param(ctx->drv_handle, type, out); - aml_vdec_unlock(ctx); + //aml_vdec_unlock(ctx); return ret; } @@ -109,11 +109,11 @@ void vdec_if_deinit(struct aml_vcodec_ctx *ctx) if (ctx->drv_handle == 0) return; - aml_vdec_lock(ctx); + //aml_vdec_lock(ctx); //aml_vcodec_dec_clock_on(&ctx->dev->pm); ctx->dec_if->deinit(ctx->drv_handle); //aml_vcodec_dec_clock_off(&ctx->dev->pm); - aml_vdec_unlock(ctx); + //aml_vdec_unlock(ctx); ctx->drv_handle = 0; } diff --git a/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_if.h b/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_if.h index 025e2cb5d29a..7e7f0e1cfb08 100644 --- a/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_if.h +++ b/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_if.h @@ -13,9 +13,9 @@ * @FB_ST_FREE : frame buffer is not used by decoder any more */ enum vdec_fb_status { - FB_ST_NORMAL = 0, - FB_ST_DISPLAY = (1 << 0), - FB_ST_FREE = (1 << 1) + FB_ST_NORMAL, + FB_ST_DISPLAY, + FB_ST_FREE }; /* For GET_PARAM_DISP_FRAME_BUFFER and GET_PARAM_FREE_FRAME_BUFFER, diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/vmh264.c b/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/vmh264.c index d77c19d61e97..5c918125d2a4 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/vmh264.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/vmh264.c @@ -1609,16 +1609,13 @@ static int v4l_get_fb(struct aml_vcodec_ctx *ctx, struct vdec_fb **out) static int alloc_one_buf_spec_from_queue(struct vdec_h264_hw_s *hw, int idx) { int ret = 0; + struct aml_vcodec_ctx *ctx = NULL; struct buffer_spec_s *bs = &hw->buffer_spec[idx]; struct canvas_config_s *y_canvas_cfg = NULL; struct canvas_config_s *c_canvas_cfg = NULL; struct vdec_fb *fb = NULL; unsigned int y_addr, c_addr; - int buf_size = (hw->mb_total << 8) + (hw->mb_total << 7); - dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, - "%s() [%d], buf size: %d\n", __FUNCTION__, __LINE__, buf_size); - if (IS_ERR_OR_NULL(hw->v4l2_ctx)) { pr_err("the v4l context has err.\n"); return -1; @@ -1627,26 +1624,31 @@ static int alloc_one_buf_spec_from_queue(struct vdec_h264_hw_s *hw, int idx) if (bs->cma_alloc_addr) return 0; + ctx = (struct aml_vcodec_ctx *)(hw->v4l2_ctx); + dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, + "[%d] %s(), buf size: %d\n", ctx->id, __func__, + (hw->mb_total << 8) + (hw->mb_total << 7)); + ret = v4l_get_fb(hw->v4l2_ctx, &fb); if (ret) { - pr_err("get fb fail.\n"); + pr_err("[%d] get fb fail.\n", ctx->id); return ret; } bs->cma_alloc_addr = (unsigned long)fb; dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, - "%s() [%d], cma alloc addr: 0x%x\n", - __FUNCTION__, __LINE__, bs->cma_alloc_addr); + "[%d] %s(), cma alloc addr: 0x%x\n", + ctx->id, __func__, bs->cma_alloc_addr); y_addr = virt_to_phys(fb->base_y.va); c_addr = virt_to_phys(fb->base_c.va); dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, - "%s() [%d], y_addr: %x, va: %p\n", - __FUNCTION__, __LINE__, y_addr, fb->base_y.va); + "[%d] %s(), y_addr: %x, va: %p\n", + ctx->id, __func__, y_addr, fb->base_y.va); dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, - "%s() [%d], c_addr: %x, va: %p\n", - __FUNCTION__, __LINE__, c_addr, fb->base_c.va); + "[%d] %s(), c_addr: %x, va: %p\n", + ctx->id, __func__, c_addr, fb->base_c.va); bs->y_addr = y_addr; bs->u_addr = c_addr; @@ -1661,7 +1663,7 @@ static int alloc_one_buf_spec_from_queue(struct vdec_h264_hw_s *hw, int idx) y_canvas_cfg->block_mode = CANVAS_BLKMODE_LINEAR; fb->base_y.bytes_used = y_canvas_cfg->width * y_canvas_cfg->height; dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, - "%s() [%d], y_w: %d, y_h: %d\n", __FUNCTION__, __LINE__, + "[%d] %s(), y_w: %d, y_h: %d\n", ctx->id, __func__, y_canvas_cfg->width,y_canvas_cfg->height); c_canvas_cfg->phy_addr = c_addr; @@ -1670,11 +1672,11 @@ static int alloc_one_buf_spec_from_queue(struct vdec_h264_hw_s *hw, int idx) c_canvas_cfg->block_mode = CANVAS_BLKMODE_LINEAR; fb->base_c.bytes_used = c_canvas_cfg->width * c_canvas_cfg->height; dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, - "%s() [%d], c_w: %d, c_h: %d\n", __FUNCTION__, __LINE__, + "[%d] %s(), c_w: %d, c_h: %d\n", ctx->id, __func__, c_canvas_cfg->width, c_canvas_cfg->height); dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, - "%s, alloc buf for bufspec%d\n", __FUNCTION__, idx); + "[%d] %s(), alloc buf for bufspec%d\n", ctx->id, __func__, idx); return ret; } @@ -2140,8 +2142,9 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) vf->v4l_mem_handle = hw->buffer_spec[buffer_index].cma_alloc_addr; dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, - "%s() [%d], v4l mem handle: 0x%x\n", - __FUNCTION__, __LINE__, vf->v4l_mem_handle); + "[%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) { @@ -2258,6 +2261,7 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) 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 vdec_fb *fb = NULL; @@ -2270,7 +2274,7 @@ int notify_v4l_eos(struct vdec_s *vdec) } if (v4l_get_fb(hw->v4l2_ctx, &fb)) { - pr_err("get fb fail.\n"); + pr_err("[%d] get fb fail.\n", ctx->id); return -1; } @@ -2279,9 +2283,10 @@ int notify_v4l_eos(struct vdec_s *vdec) vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L; kfifo_put(&hw->display_q, (const struct vframe_s *)vf); - pr_info("264 EOS notify \n"); vf_notify_receiver(vdec->vf_provider_name, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + + pr_info("[%d] H264 EOS notify.\n", ctx->id); } return 0; @@ -3604,7 +3609,7 @@ static int vh264_set_params(struct vdec_h264_hw_s *hw, (unsigned int)((8 << chroma444) - 1)); } dpb_print(DECODE_ID(hw), 0, - "frame_mbs_only_flag %d, crop_bottom %d, frame_height %d, ", + "frame_mbs_only_flag %d, crop_bottom %d, frame_height %d,\n", frame_mbs_only_flag, crop_bottom, hw->frame_height); dpb_print(DECODE_ID(hw), 0, "mb_height %d,crop_right %d, frame_width %d, mb_width %d\n", @@ -3755,12 +3760,13 @@ static int vh264_set_params(struct vdec_h264_hw_s *hw, for (j = 1; j < buf_cnt; j++) { i = get_buf_spec_by_canvas_pos(hw, j); - if (hw->is_used_v4l && - alloc_one_buf_spec_from_queue + if (hw->is_used_v4l) { + if (alloc_one_buf_spec_from_queue (hw, i) < 0) { - if (j++ != buf_cnt) - ret = -1; - break; + if (j++ != buf_cnt) + ret = -1; + break; + } } else if (alloc_one_buf_spec(hw, i) < 0) break; @@ -3974,9 +3980,12 @@ static void vui_config(struct vdec_h264_hw_s *hw) static void bufmgr_recover(struct vdec_h264_hw_s *hw) { struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; + bufmgr_h264_remove_unused_frame(p_H264_Dpb, 2); - if (error_proc_policy & 0x20) - hw->reset_bufmgr_flag = 1; + if (error_proc_policy & 0x20) { + if (!hw->is_used_v4l) + hw->reset_bufmgr_flag = 1; + } } void bufmgr_force_recover(struct h264_dpb_stru *p_H264_Dpb) @@ -5207,6 +5216,10 @@ static int vh264_hw_ctx_restore(struct vdec_h264_hw_s *hw) SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1<<17); #endif + /* cbcr_merge_swap_en */ + if (hw->is_used_v4l) + SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 16); + SET_VREG_MASK(MDEC_PIC_DC_CTRL, 0xbf << 24); CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 0xbf << 24); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.c index 3369043927b1..4838a6fa1796 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.c @@ -1581,7 +1581,8 @@ s32 vdec_init(struct vdec_s *vdec, int is_4k) "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", vdec->vf_provider_name, "v4l2-video"); + "%s %s", vdec->vf_provider_name, + vdec->vf_receiver_name); snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE, "vdec-map-%d", vdec->id); } @@ -2442,6 +2443,7 @@ void vdec_poweron(enum vdec_type_e core) * m8baby and m8m2 can dynamic adjust vdec clock, * power on with default clock level */ + amports_switch_gate("clk_vdec_mux", 1); vdec_clock_hi_enable(); /* power up vdec memories */ WRITE_VREG(DOS_MEM_PD_VDEC, 0); @@ -2519,6 +2521,9 @@ void vdec_poweron(enum vdec_type_e core) WRITE_VREG(DOS_SW_RESET3, 0xffffffff); WRITE_VREG(DOS_SW_RESET3, 0); /* enable hevc clock */ + amports_switch_gate("clk_hevc_mux", 1); + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) + amports_switch_gate("clk_hevcb_mux", 1); hevc_clock_hi_enable(); hevc_back_clock_hi_enable(); /* power up hevc memories */ diff --git a/drivers/amlogic/media_modules/stream_input/amports/amstream.c b/drivers/amlogic/media_modules/stream_input/amports/amstream.c index 730d24a005ef..a7927009c6d3 100644 --- a/drivers/amlogic/media_modules/stream_input/amports/amstream.c +++ b/drivers/amlogic/media_modules/stream_input/amports/amstream.c @@ -612,10 +612,6 @@ static int video_port_init(struct port_priv_s *priv, pbuf->for_4k = 1; if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_TXLX && port->vformat == VFORMAT_H264) { - amports_switch_gate("clk_hevc_mux", 1); - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) - amports_switch_gate("clk_hevcb_mux", 1); - vdec_poweron(VDEC_HEVC); } } else { @@ -1620,22 +1616,14 @@ static int amstream_open(struct inode *inode, struct file *file) if (has_hevc_vdec()) { if (port->type & - (PORT_TYPE_MPTS | PORT_TYPE_HEVC)) { - amports_switch_gate("clk_hevc_mux", 1); - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) - amports_switch_gate("clk_hevcb_mux", 1); + (PORT_TYPE_MPTS | PORT_TYPE_HEVC)) vdec_poweron(VDEC_HEVC); - } - if ((port->type & PORT_TYPE_HEVC) == 0) { - amports_switch_gate("clk_vdec_mux", 1); + if ((port->type & PORT_TYPE_HEVC) == 0) vdec_poweron(VDEC_1); - } } else { - if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) { - amports_switch_gate("clk_vdec_mux", 1); + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) vdec_poweron(VDEC_1); - } } }