static void vb2ops_vdec_buf_queue(struct vb2_buffer *vb) { struct vb2_buffer *src_buf; struct mtk_vcodec_mem src_mem; bool res_chg = false; int ret = 0; unsigned int dpbsize = 1; struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); struct vb2_v4l2_buffer *vb2_v4l2 = NULL; struct mtk_video_dec_buf *buf = NULL; mtk_v4l2_debug(3, "[%d] (%d) id=%d, vb=%p", ctx->id, vb->vb2_queue->type, vb->index, vb); /* * check if this buffer is ready to be used after decode */ if (vb->vb2_queue->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { vb2_v4l2 = to_vb2_v4l2_buffer(vb); buf = container_of(vb2_v4l2, struct mtk_video_dec_buf, vb); mutex_lock(&ctx->lock); if (buf->used == false) { v4l2_m2m_buf_queue(ctx->m2m_ctx, vb2_v4l2); buf->queued_in_vb2 = true; buf->queued_in_v4l2 = true; buf->ready_to_display = false; } else { buf->queued_in_vb2 = false; buf->queued_in_v4l2 = true; buf->ready_to_display = false; } mutex_unlock(&ctx->lock); return; }
static void rot_vb2_buf_queue(struct vb2_buffer *vb) { struct rot_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); if (ctx->m2m_ctx) v4l2_m2m_buf_queue(ctx->m2m_ctx, vb); }
static void jpeg_hx_enc_buf_queue(struct vb2_buffer *vb) { struct jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); if (ctx->m2m_ctx) v4l2_m2m_buf_queue(ctx->m2m_ctx, vb); }
static void hva_buf_queue(struct vb2_buffer *vb) { struct hva_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); if (ctx->fh.m2m_ctx) v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); }
/* * msm_jpegdma_buf_queue - vb2_ops buf_queue callback. * @vb: Pointer to vb2 buffer struct. */ static void msm_jpegdma_buf_queue(struct vb2_buffer *vb) { struct jpegdma_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); v4l2_m2m_buf_queue(ctx->m2m_ctx, vb); return; }
static void fimc_buf_queue(struct vb2_buffer *vb) { struct fimc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); dbg("ctx: %p, ctx->state: 0x%x", ctx, ctx->state); if (ctx->m2m_ctx) v4l2_m2m_buf_queue(ctx->m2m_ctx, vb); }
static void gsc_m2m_buf_queue(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct gsc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); pr_debug("ctx: %p, ctx->state: 0x%x", ctx, ctx->state); if (ctx->m2m_ctx) v4l2_m2m_buf_queue(ctx->m2m_ctx, vbuf); }
static void bdisp_buf_queue(struct vb2_buffer *vb) { struct bdisp_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); /* return to V4L2 any 0-size buffer so it can be dequeued by user */ if (!vb2_get_plane_payload(vb, 0)) { dev_dbg(ctx->bdisp_dev->dev, "0 data buffer, skip it\n"); vb2_buffer_done(vb, VB2_BUF_STATE_DONE); return; } if (ctx->fh.m2m_ctx) v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb); }
static void gsc_m2m_buf_queue(struct vb2_buffer *vb) { struct gsc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); struct v4l2_m2m_buffer *b = container_of(vb, struct v4l2_m2m_buffer, vb); unsigned long flags; struct sync_fence *fence; gsc_dbg("ctx: %p, ctx->state: 0x%x", ctx, ctx->state); fence = vb->acquire_fence; if (fence) { spin_lock_irqsave(&ctx->slock, flags); list_add_tail(&b->wait, &ctx->fence_wait_list); spin_unlock_irqrestore(&ctx->slock, flags); queue_work(ctx->gsc_dev->irq_workqueue, &ctx->fence_work); } else { if (ctx->m2m_ctx) v4l2_m2m_buf_queue(ctx->m2m_ctx, vb); } }
static int vidioc_decoder_cmd(struct file *file, void *priv, struct v4l2_decoder_cmd *cmd) { struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv); struct vb2_queue *src_vq, *dst_vq; int ret; ret = vidioc_try_decoder_cmd(file, priv, cmd); if (ret) return ret; mtk_v4l2_debug(1, "decoder cmd=%u", 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: src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); if (!vb2_is_streaming(src_vq)) { mtk_v4l2_debug(1, "Output stream is off. No need to flush."); return 0; } if (!vb2_is_streaming(dst_vq)) { mtk_v4l2_debug(1, "Capture stream is off. No need to flush."); return 0; } v4l2_m2m_buf_queue(ctx->m2m_ctx, &ctx->empty_flush_buf->vb); v4l2_m2m_try_schedule(ctx->m2m_ctx); break; case V4L2_DEC_CMD_START: vb2_clear_last_buffer_dequeued(dst_vq); break; default: return -EINVAL; } return 0; }
/* real queue!!! */ static void nxp_vb2_buf_queue(struct vb2_buffer *vb) { struct nxp_video *me = vb->vb2_queue->drv_priv; struct nxp_video_buffer *buf; struct nxp_buffer_consumer *c; u32 type = vb->vb2_queue->type; int ret; if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { buf = me->sink_bufs[vb->v4l2_buf.index]; c = _find_consumer(me, &me->sink_consumer_list, 0); } else if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { buf = me->source_bufs[vb->v4l2_buf.index]; c = _find_consumer(me, &me->source_consumer_list, 0); } else { pr_err("%s: invalid buffer type(0x%x)\n", __func__, type); return; } if (!buf || !c) { pr_err("%s: No consumer or No buf!!!\n", __func__); return; } ret = _fill_nxp_video_buffer(buf, vb); if (ret < 0) { pr_err("%s: fatal error!!!\n", __func__); vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); return; } pr_debug("%s buf(%p)\n", __func__, buf); c->queue(buf, c->priv); /* for m2m : TODO */ #if 0 if (me->type == NXP_VIDEO_TYPE_M2M) v4l2_m2m_buf_queue(me->m2m_ctx, vb); #endif }
static void vb2ops_venc_buf_queue(struct vb2_buffer *vb) { struct mtk_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 mtk_video_enc_buf *mtk_buf = container_of(vb2_v4l2, struct mtk_video_enc_buf, vb); if ((vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) && (ctx->param_change != MTK_ENCODE_PARAM_NONE)) { mtk_v4l2_debug(1, "[%d] Before id=%d encode parameter change %x", ctx->id, mtk_buf->vb.vb2_buf.index, ctx->param_change); mtk_buf->param_change = ctx->param_change; mtk_buf->enc_params = ctx->enc_params; ctx->param_change = MTK_ENCODE_PARAM_NONE; } v4l2_m2m_buf_queue(ctx->m2m_ctx, to_vb2_v4l2_buffer(vb)); }
static void gsc_m2m_fence_work(struct work_struct *work) { struct gsc_ctx *ctx = container_of(work, struct gsc_ctx, fence_work); struct v4l2_m2m_buffer *buffer; struct sync_fence *fence; unsigned long flags; int ret; spin_lock_irqsave(&ctx->slock, flags); while (!list_empty(&ctx->fence_wait_list)) { buffer = list_first_entry(&ctx->fence_wait_list, struct v4l2_m2m_buffer, wait); list_del(&buffer->wait); spin_unlock_irqrestore(&ctx->slock, flags); fence = buffer->vb.acquire_fence; if (fence) { buffer->vb.acquire_fence = NULL; ret = sync_fence_wait(fence, 1000); if (ret == -ETIME) { gsc_warn("sync_fence_wait() timeout"); ret = sync_fence_wait(fence, 10 * MSEC_PER_SEC); } if (ret) gsc_warn("sync_fence_wait() error"); sync_fence_put(fence); } if (ctx->m2m_ctx) { v4l2_m2m_buf_queue(ctx->m2m_ctx, &buffer->vb); v4l2_m2m_try_schedule(ctx->m2m_ctx); } spin_lock_irqsave(&ctx->slock, flags); } spin_unlock_irqrestore(&ctx->slock, flags); }
static void fimc_buf_queue(struct vb2_buffer *vb) { struct fimc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb); }
static void g2d_buf_queue(struct vb2_buffer *vb) { struct g2d_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); v4l2_m2m_buf_queue(ctx->m2m_ctx, vb); }
/* * This function tries to clean all capture buffers that are not used as * reference buffers by codec driver any more * In this case, we need re-queue buffer to vb2 buffer if user space * already returns this buffer to v4l2 or this buffer is just the output of * previous sps/pps/resolution change decode, or do nothing if user * space still owns this buffer */ static struct vb2_buffer *get_free_buffer(struct mtk_vcodec_ctx *ctx) { struct mtk_video_dec_buf *dstbuf; struct vdec_fb *free_frame_buffer = NULL; if (vdec_if_get_param(ctx, GET_PARAM_FREE_FRAME_BUFFER, &free_frame_buffer)) { mtk_v4l2_err("[%d] Error!! Cannot get param", ctx->id); return NULL; } if (free_frame_buffer == NULL) { mtk_v4l2_debug(3, " No free frame buffer"); return NULL; } mtk_v4l2_debug(3, "[%d] tmp_frame_addr = 0x%p", ctx->id, free_frame_buffer); dstbuf = container_of(free_frame_buffer, struct mtk_video_dec_buf, frame_buffer); mutex_lock(&ctx->lock); if (dstbuf->used) { if ((dstbuf->queued_in_vb2) && (dstbuf->queued_in_v4l2) && (free_frame_buffer->status == FB_ST_FREE)) { /* * After decode sps/pps or non-display buffer, we don't * need to return capture buffer to user space, but * just re-queue this capture buffer to vb2 queue. * This reduce overheads that dq/q unused capture * buffer. In this case, queued_in_vb2 = true. */ mtk_v4l2_debug(2, "[%d]status=%x queue id=%d to rdy_queue %d", ctx->id, free_frame_buffer->status, dstbuf->vb.vb2_buf.index, dstbuf->queued_in_vb2); v4l2_m2m_buf_queue(ctx->m2m_ctx, &dstbuf->vb); } else if ((dstbuf->queued_in_vb2 == false) && (dstbuf->queued_in_v4l2 == true)) { /* * If buffer in v4l2 driver but not in vb2 queue yet, * and we get this buffer from free_list, it means * that codec driver do not use this buffer as * reference buffer anymore. We should q buffer to vb2 * queue, so later work thread could get this buffer * for decode. In this case, queued_in_vb2 = false * means this buffer is not from previous decode * output. */ mtk_v4l2_debug(2, "[%d]status=%x queue id=%d to rdy_queue", ctx->id, free_frame_buffer->status, dstbuf->vb.vb2_buf.index); v4l2_m2m_buf_queue(ctx->m2m_ctx, &dstbuf->vb); dstbuf->queued_in_vb2 = true; } else { /* * Codec driver do not need to reference this capture * buffer and this buffer is not in v4l2 driver. * Then we don't need to do any thing, just add log when * we need to debug buffer flow. * When this buffer q from user space, it could * directly q to vb2 buffer */ mtk_v4l2_debug(3, "[%d]status=%x err queue id=%d %d %d", ctx->id, free_frame_buffer->status, dstbuf->vb.vb2_buf.index, dstbuf->queued_in_vb2, dstbuf->queued_in_v4l2); } dstbuf->used = false; } mutex_unlock(&ctx->lock); return &dstbuf->vb.vb2_buf; }