Like for vb queues remove VB2_MAX_FRAME upper limit on postprocessor buffers storage capacity. If a buffer hasn't been allocated when setting up the queue make possible to alloc it on the fly while streaming. This happens when resolution change between keyframes. Signed-off-by: Benjamin Gaignard <benjamin.gaignard@xxxxxxxxxxxxx> --- drivers/media/platform/verisilicon/hantro.h | 6 +- .../media/platform/verisilicon/hantro_hw.h | 6 +- .../platform/verisilicon/hantro_postproc.c | 109 ++++++++++++------ .../media/platform/verisilicon/hantro_v4l2.c | 12 +- 4 files changed, 82 insertions(+), 51 deletions(-) diff --git a/drivers/media/platform/verisilicon/hantro.h b/drivers/media/platform/verisilicon/hantro.h index 2989ebc631cc..bd0dca11b90a 100644 --- a/drivers/media/platform/verisilicon/hantro.h +++ b/drivers/media/platform/verisilicon/hantro.h @@ -460,12 +460,14 @@ hantro_get_dst_buf(struct hantro_ctx *ctx) bool hantro_needs_postproc(const struct hantro_ctx *ctx, const struct hantro_fmt *fmt); +dma_addr_t +hantro_postproc_get_dec_buf_addr(struct hantro_ctx *ctx, int index); static inline dma_addr_t hantro_get_dec_buf_addr(struct hantro_ctx *ctx, struct vb2_buffer *vb) { if (hantro_needs_postproc(ctx, ctx->vpu_dst_fmt)) - return ctx->postproc.dec_q[vb->index].dma; + return hantro_postproc_get_dec_buf_addr(ctx, vb->index); return vb2_dma_contig_plane_dma_addr(vb, 0); } @@ -477,8 +479,8 @@ vb2_to_hantro_decoded_buf(struct vb2_buffer *buf) void hantro_postproc_disable(struct hantro_ctx *ctx); void hantro_postproc_enable(struct hantro_ctx *ctx); +int hantro_postproc_init(struct hantro_ctx *ctx); void hantro_postproc_free(struct hantro_ctx *ctx); -int hantro_postproc_alloc(struct hantro_ctx *ctx); int hanto_postproc_enum_framesizes(struct hantro_ctx *ctx, struct v4l2_frmsizeenum *fsize); diff --git a/drivers/media/platform/verisilicon/hantro_hw.h b/drivers/media/platform/verisilicon/hantro_hw.h index 9e8faf7ba6fb..5c7b6e04aded 100644 --- a/drivers/media/platform/verisilicon/hantro_hw.h +++ b/drivers/media/platform/verisilicon/hantro_hw.h @@ -15,8 +15,6 @@ #include <media/v4l2-vp9.h> #include <media/videobuf2-core.h> -#define VB2_MAX_FRAME 32 - #define DEC_8190_ALIGN_MASK 0x07U #define MB_DIM 16 @@ -252,10 +250,10 @@ struct hantro_vp9_dec_hw_ctx { /** * struct hantro_postproc_ctx * - * @dec_q: References buffers, in decoder format. + * @dec_refs_xa: References buffers, in decoder format. */ struct hantro_postproc_ctx { - struct hantro_aux_buf dec_q[VB2_MAX_FRAME]; + struct xarray dec_refs_xa; }; /** diff --git a/drivers/media/platform/verisilicon/hantro_postproc.c b/drivers/media/platform/verisilicon/hantro_postproc.c index 6437423ccf3a..a6b67d0cc66c 100644 --- a/drivers/media/platform/verisilicon/hantro_postproc.c +++ b/drivers/media/platform/verisilicon/hantro_postproc.c @@ -170,36 +170,23 @@ static int hantro_postproc_g2_enum_framesizes(struct hantro_ctx *ctx, return 0; } -void hantro_postproc_free(struct hantro_ctx *ctx) +static int hantro_postproc_alloc(struct hantro_ctx *ctx, int index) { struct hantro_dev *vpu = ctx->dev; - unsigned int i; - - for (i = 0; i < VB2_MAX_FRAME; ++i) { - struct hantro_aux_buf *priv = &ctx->postproc.dec_q[i]; - - if (priv->cpu) { - dma_free_attrs(vpu->dev, priv->size, priv->cpu, - priv->dma, priv->attrs); - priv->cpu = NULL; - } - } -} - -int hantro_postproc_alloc(struct hantro_ctx *ctx) -{ - struct hantro_dev *vpu = ctx->dev; - struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx; - struct vb2_queue *cap_queue = &m2m_ctx->cap_q_ctx.q; - unsigned int num_buffers = cap_queue->num_buffers; struct v4l2_pix_format_mplane pix_mp; const struct hantro_fmt *fmt; - unsigned int i, buf_size; + struct hantro_aux_buf *priv; + unsigned int buf_size; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; /* this should always pick native format */ fmt = hantro_get_default_fmt(ctx, false, ctx->bit_depth); if (!fmt) return -EINVAL; + v4l2_fill_pixfmt_mp(&pix_mp, fmt->fourcc, ctx->src_fmt.width, ctx->src_fmt.height); @@ -214,20 +201,74 @@ int hantro_postproc_alloc(struct hantro_ctx *ctx) buf_size += hantro_hevc_mv_size(pix_mp.width, pix_mp.height); - for (i = 0; i < num_buffers; ++i) { - struct hantro_aux_buf *priv = &ctx->postproc.dec_q[i]; - - /* - * The buffers on this queue are meant as intermediate - * buffers for the decoder, so no mapping is needed. - */ - priv->attrs = DMA_ATTR_NO_KERNEL_MAPPING; - priv->cpu = dma_alloc_attrs(vpu->dev, buf_size, &priv->dma, - GFP_KERNEL, priv->attrs); - if (!priv->cpu) - return -ENOMEM; - priv->size = buf_size; + /* + * The buffers on this queue are meant as intermediate + * buffers for the decoder, so no mapping is needed. + */ + priv->attrs = DMA_ATTR_NO_KERNEL_MAPPING; + priv->cpu = dma_alloc_attrs(vpu->dev, buf_size, &priv->dma, GFP_KERNEL, priv->attrs); + if (!priv->cpu) + return -ENOMEM; + + priv->size = buf_size; + + xa_store(&ctx->postproc.dec_refs_xa, index, priv, GFP_KERNEL); + + return 0; +} + +void hantro_postproc_free(struct hantro_ctx *ctx) +{ + struct hantro_dev *vpu = ctx->dev; + struct hantro_aux_buf *priv; + unsigned long i; + + xa_for_each(&ctx->postproc.dec_refs_xa, i, priv) { + dma_free_attrs(vpu->dev, priv->size, priv->cpu, priv->dma, priv->attrs); + kfree(priv); + } + + xa_destroy(&ctx->postproc.dec_refs_xa); +} + +int hantro_postproc_init(struct hantro_ctx *ctx) +{ + struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx; + struct vb2_queue *cap_queue = &m2m_ctx->cap_q_ctx.q; + unsigned int num_buffers = cap_queue->num_buffers; + int i, ret = 0; + + xa_init_flags(&ctx->postproc.dec_refs_xa, XA_FLAGS_ALLOC); + + for (i = 0; i < num_buffers; i++) { + ret = hantro_postproc_alloc(ctx, i); + if (ret < 0) { + hantro_postproc_free(ctx); + return ret; + } } + + return ret; +} + +dma_addr_t +hantro_postproc_get_dec_buf_addr(struct hantro_ctx *ctx, int index) +{ + struct hantro_aux_buf *priv = xa_load(&ctx->postproc.dec_refs_xa, index); + int ret; + + if (priv) + return priv->dma; + + /* buffer not already allocated, try getting a new one */ + ret = hantro_postproc_alloc(ctx, index); + if (ret < 0) + return 0; + + priv = xa_load(&ctx->postproc.dec_refs_xa, index); + if (priv) + return priv->dma; + return 0; } diff --git a/drivers/media/platform/verisilicon/hantro_v4l2.c b/drivers/media/platform/verisilicon/hantro_v4l2.c index 61cfaaf4e927..0f615c1001c0 100644 --- a/drivers/media/platform/verisilicon/hantro_v4l2.c +++ b/drivers/media/platform/verisilicon/hantro_v4l2.c @@ -894,20 +894,10 @@ static int hantro_start_streaming(struct vb2_queue *q, unsigned int count) ret = ctx->codec_ops->init(ctx); if (ret) return ret; - } - - if (hantro_needs_postproc(ctx, ctx->vpu_dst_fmt)) { - ret = hantro_postproc_alloc(ctx); - if (ret) - goto err_codec_exit; + ret = hantro_postproc_init(ctx); } } return ret; - -err_codec_exit: - if (ctx->codec_ops->exit) - ctx->codec_ops->exit(ctx); - return ret; } static void -- 2.39.2