Le lundi 02 novembre 2026 à 18:03 +0100, Jernej Skrabec a écrit : > Above 2048 pixels, the deblocking and intra prediction row buffers don't > fit into the internal SRAM anymore. Put them into DRAM like H.264 does. > The vendor library sizes the deblocking buffer as 24 bytes per column. > > Tested on H616 with 2560x1440 and 3840x2160 libvpx streams, which are > bit-exact with the FFmpeg software decoder. > > Signed-off-by: Jernej Skrabec Reviewed-by: Nicolas Dufresne > --- > drivers/staging/media/sunxi/cedrus/cedrus.h | 7 ++ > .../staging/media/sunxi/cedrus/cedrus_vp8.c | 64 +++++++++++++++++++ > 2 files changed, 71 insertions(+) > > diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h > index d28fe91562d1..ca4efa9302fc 100644 > --- a/drivers/staging/media/sunxi/cedrus/cedrus.h > +++ b/drivers/staging/media/sunxi/cedrus/cedrus.h > @@ -156,6 +156,13 @@ struct cedrus_ctx { > > u8 *entropy_probs_buf; > dma_addr_t entropy_probs_buf_dma; > + > + void *deblk_buf; > + dma_addr_t deblk_buf_dma; > + ssize_t deblk_buf_size; > + void *intra_pred_buf; > + dma_addr_t intra_pred_buf_dma; > + ssize_t intra_pred_buf_size; > } vp8; > } codec; > }; > diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_vp8.c b/drivers/staging/media/sunxi/cedrus/cedrus_vp8.c > index 6b00efa77c22..954c0ceb98ed 100644 > --- a/drivers/staging/media/sunxi/cedrus/cedrus_vp8.c > +++ b/drivers/staging/media/sunxi/cedrus/cedrus_vp8.c > @@ -666,6 +666,20 @@ static int cedrus_vp8_setup(struct cedrus_ctx *ctx, struct cedrus_run *run) > > cedrus_write(dev, VE_H264_CTRL, VE_H264_CTRL_VP8); > > + if (ctx->codec.vp8.deblk_buf_size) { > + cedrus_write(dev, VE_BUF_CTRL, > + VE_BUF_CTRL_INTRAPRED_MIXED_RAM | > + VE_BUF_CTRL_DBLK_MIXED_RAM); > + cedrus_write(dev, VE_DBLK_DRAM_BUF_ADDR, > + ctx->codec.vp8.deblk_buf_dma); > + cedrus_write(dev, VE_INTRAPRED_DRAM_BUF_ADDR, > + ctx->codec.vp8.intra_pred_buf_dma); > + } else { > + cedrus_write(dev, VE_BUF_CTRL, > + VE_BUF_CTRL_INTRAPRED_INT_SRAM | > + VE_BUF_CTRL_DBLK_INT_SRAM); > + } > + > cedrus_vp8_update_probs(slice, ctx->codec.vp8.entropy_probs_buf); > > reg = slice->first_part_size * 8; > @@ -849,7 +863,44 @@ static int cedrus_vp8_start(struct cedrus_ctx *ctx) > memcpy(&ctx->codec.vp8.entropy_probs_buf[2048], > prob_table_init, sizeof(prob_table_init)); > > + /* > + * Above 2048 pixels the deblocking and intra prediction row buffers > + * no longer fit into the internal SRAM. The vendor library sizes the > + * deblocking buffer as 24 bytes per (32 aligned) column. > + */ > + if (ctx->src_fmt.width > 2048) { > + ctx->codec.vp8.deblk_buf_size = > + ALIGN(ctx->src_fmt.width, 32) * 24; > + ctx->codec.vp8.deblk_buf = > + dma_alloc_attrs(dev->dev, ctx->codec.vp8.deblk_buf_size, > + &ctx->codec.vp8.deblk_buf_dma, > + GFP_KERNEL, DMA_ATTR_NO_KERNEL_MAPPING); > + if (!ctx->codec.vp8.deblk_buf) > + goto err_probs; > + > + ctx->codec.vp8.intra_pred_buf_size = > + ALIGN(ctx->src_fmt.width, 64) * 5 * 2; > + ctx->codec.vp8.intra_pred_buf = > + dma_alloc_attrs(dev->dev, > + ctx->codec.vp8.intra_pred_buf_size, > + &ctx->codec.vp8.intra_pred_buf_dma, > + GFP_KERNEL, DMA_ATTR_NO_KERNEL_MAPPING); > + if (!ctx->codec.vp8.intra_pred_buf) > + goto err_deblk; > + } > + > return 0; > + > +err_deblk: > + dma_free_attrs(dev->dev, ctx->codec.vp8.deblk_buf_size, > + ctx->codec.vp8.deblk_buf, ctx->codec.vp8.deblk_buf_dma, > + DMA_ATTR_NO_KERNEL_MAPPING); > + ctx->codec.vp8.deblk_buf_size = 0; > +err_probs: > + dma_free_coherent(dev->dev, CEDRUS_ENTROPY_PROBS_SIZE, > + ctx->codec.vp8.entropy_probs_buf, > + ctx->codec.vp8.entropy_probs_buf_dma); > + return -ENOMEM; > } > > static void cedrus_vp8_stop(struct cedrus_ctx *ctx) > @@ -861,6 +912,19 @@ static void cedrus_vp8_stop(struct cedrus_ctx *ctx) > dma_free_coherent(dev->dev, CEDRUS_ENTROPY_PROBS_SIZE, > ctx->codec.vp8.entropy_probs_buf, > ctx->codec.vp8.entropy_probs_buf_dma); > + > + if (ctx->codec.vp8.deblk_buf_size) { > + dma_free_attrs(dev->dev, ctx->codec.vp8.deblk_buf_size, > + ctx->codec.vp8.deblk_buf, > + ctx->codec.vp8.deblk_buf_dma, > + DMA_ATTR_NO_KERNEL_MAPPING); > + dma_free_attrs(dev->dev, ctx->codec.vp8.intra_pred_buf_size, > + ctx->codec.vp8.intra_pred_buf, > + ctx->codec.vp8.intra_pred_buf_dma, > + DMA_ATTR_NO_KERNEL_MAPPING); > + ctx->codec.vp8.deblk_buf_size = 0; > + ctx->codec.vp8.intra_pred_buf_size = 0; > + } > } > > static void cedrus_vp8_trigger(struct cedrus_ctx *ctx)