static int hva_buf_prepare(struct vb2_buffer *vb) { struct hva_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); struct device *dev = ctx_to_dev(ctx); struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); if (vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { struct hva_frame *frame = to_hva_frame(vbuf); if (vbuf->field == V4L2_FIELD_ANY) vbuf->field = V4L2_FIELD_NONE; if (vbuf->field != V4L2_FIELD_NONE) { dev_dbg(dev, "%s frame[%d] prepare: %d field not supported\n", ctx->name, vb->index, vbuf->field); return -EINVAL; } if (!frame->prepared) { /* get memory addresses */ frame->vaddr = vb2_plane_vaddr(&vbuf->vb2_buf, 0); frame->paddr = vb2_dma_contig_plane_dma_addr( &vbuf->vb2_buf, 0); frame->info = ctx->frameinfo; frame->prepared = true; dev_dbg(dev, "%s frame[%d] prepared; virt=%p, phy=%pad\n", ctx->name, vb->index, frame->vaddr, &frame->paddr); } } else { struct hva_stream *stream = to_hva_stream(vbuf); if (!stream->prepared) { /* get memory addresses */ stream->vaddr = vb2_plane_vaddr(&vbuf->vb2_buf, 0); stream->paddr = vb2_dma_contig_plane_dma_addr( &vbuf->vb2_buf, 0); stream->size = vb2_plane_size(&vbuf->vb2_buf, 0); stream->prepared = true; dev_dbg(dev, "%s stream[%d] prepared; virt=%p, phy=%pad\n", ctx->name, vb->index, stream->vaddr, &stream->paddr); } } return 0; }
static void hva_run_work(struct work_struct *work) { struct hva_ctx *ctx = container_of(work, struct hva_ctx, run_work); struct vb2_v4l2_buffer *src_buf, *dst_buf; const struct hva_enc *enc = ctx->enc; struct hva_frame *frame; struct hva_stream *stream; int ret; /* protect instance against reentrancy */ mutex_lock(&ctx->lock); #ifdef CONFIG_VIDEO_STI_HVA_DEBUGFS hva_dbg_perf_begin(ctx); #endif src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); frame = to_hva_frame(src_buf); stream = to_hva_stream(dst_buf); frame->vbuf.sequence = ctx->frame_num++; ret = enc->encode(ctx, frame, stream); vb2_set_plane_payload(&dst_buf->vb2_buf, 0, stream->bytesused); if (ret) { v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR); v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR); } else { /* propagate frame timestamp */ dst_buf->vb2_buf.timestamp = src_buf->vb2_buf.timestamp; dst_buf->field = V4L2_FIELD_NONE; dst_buf->sequence = ctx->stream_num - 1; ctx->encoded_frames++; #ifdef CONFIG_VIDEO_STI_HVA_DEBUGFS hva_dbg_perf_end(ctx, stream); #endif v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE); } mutex_unlock(&ctx->lock); v4l2_m2m_job_finish(ctx->hva_dev->m2m_dev, ctx->fh.m2m_ctx); }