}
 
 static inline dma_addr_t
-cedrus_h265_frame_info_mv_col_buf_addr(struct cedrus_ctx *ctx,
-                                      unsigned int index, unsigned int field)
+cedrus_h265_frame_info_mv_col_buf_addr(struct vb2_buffer *buf,
+                                      unsigned int field)
 {
-       return ctx->codec.h265.mv_col_buf_addr + index *
-              ctx->codec.h265.mv_col_buf_unit_size +
-              field * ctx->codec.h265.mv_col_buf_unit_size / 2;
+       struct cedrus_buffer *cedrus_buf = vb2_to_cedrus_buffer(buf);
+
+       return cedrus_buf->codec.h265.mv_col_buf_dma +
+              field * cedrus_buf->codec.h265.mv_col_buf_size / 2;
 }
 
 static void cedrus_h265_frame_info_write_single(struct cedrus_ctx *ctx,
        dma_addr_t dst_luma_addr = cedrus_dst_buf_addr(ctx, buf, 0);
        dma_addr_t dst_chroma_addr = cedrus_dst_buf_addr(ctx, buf, 1);
        dma_addr_t mv_col_buf_addr[2] = {
-               cedrus_h265_frame_info_mv_col_buf_addr(ctx, buf->index, 0),
-               cedrus_h265_frame_info_mv_col_buf_addr(ctx, buf->index,
-                                                      field_pic ? 1 : 0)
+               cedrus_h265_frame_info_mv_col_buf_addr(buf, 0),
+               cedrus_h265_frame_info_mv_col_buf_addr(buf, field_pic ? 1 : 0)
        };
        u32 offset = VE_DEC_H265_SRAM_OFFSET_FRAME_INFO +
                     VE_DEC_H265_SRAM_OFFSET_FRAME_INFO_UNIT * index;
        unsigned int width_in_ctb_luma, ctb_size_luma;
        unsigned int log2_max_luma_coding_block_size;
        unsigned int ctb_addr_x, ctb_addr_y;
+       struct cedrus_buffer *cedrus_buf;
        dma_addr_t src_buf_addr;
        dma_addr_t src_buf_end_addr;
        u32 chroma_log2_weight_denom;
        decode_params = run->h265.decode_params;
        pred_weight_table = &slice_params->pred_weight_table;
        num_entry_point_offsets = slice_params->num_entry_point_offsets;
+       cedrus_buf = vb2_to_cedrus_buffer(&run->dst->vb2_buf);
 
        /*
         * If entry points offsets are present, we should get them
                DIV_ROUND_UP(sps->pic_width_in_luma_samples, ctb_size_luma);
 
        /* MV column buffer size and allocation. */
-       if (!ctx->codec.h265.mv_col_buf_size) {
-               unsigned int num_buffers =
-                       run->dst->vb2_buf.vb2_queue->num_buffers;
-
+       if (!cedrus_buf->codec.h265.mv_col_buf_size) {
                /*
                 * Each CTB requires a MV col buffer with a specific unit size.
                 * Since the address is given with missing lsb bits, 1 KiB is
                 * added to each buffer to ensure proper alignment.
                 */
-               ctx->codec.h265.mv_col_buf_unit_size =
+               cedrus_buf->codec.h265.mv_col_buf_size =
                        DIV_ROUND_UP(ctx->src_fmt.width, ctb_size_luma) *
                        DIV_ROUND_UP(ctx->src_fmt.height, ctb_size_luma) *
                        CEDRUS_H265_MV_COL_BUF_UNIT_CTB_SIZE + SZ_1K;
 
-               ctx->codec.h265.mv_col_buf_size = num_buffers *
-                       ctx->codec.h265.mv_col_buf_unit_size;
-
                /* Buffer is never accessed by CPU, so we can skip kernel mapping. */
-               ctx->codec.h265.mv_col_buf =
+               cedrus_buf->codec.h265.mv_col_buf =
                        dma_alloc_attrs(dev->dev,
-                                       ctx->codec.h265.mv_col_buf_size,
-                                       &ctx->codec.h265.mv_col_buf_addr,
+                                       cedrus_buf->codec.h265.mv_col_buf_size,
+                                       &cedrus_buf->codec.h265.mv_col_buf_dma,
                                        GFP_KERNEL, DMA_ATTR_NO_KERNEL_MAPPING);
-               if (!ctx->codec.h265.mv_col_buf) {
-                       ctx->codec.h265.mv_col_buf_size = 0;
+               if (!cedrus_buf->codec.h265.mv_col_buf) {
+                       cedrus_buf->codec.h265.mv_col_buf_size = 0;
                        return -ENOMEM;
                }
        }
 {
        struct cedrus_dev *dev = ctx->dev;
 
-       /* The buffer size is calculated at setup time. */
-       ctx->codec.h265.mv_col_buf_size = 0;
-
        /* Buffer is never accessed by CPU, so we can skip kernel mapping. */
        ctx->codec.h265.neighbor_info_buf =
                dma_alloc_attrs(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE,
 static void cedrus_h265_stop(struct cedrus_ctx *ctx)
 {
        struct cedrus_dev *dev = ctx->dev;
+       struct cedrus_buffer *buf;
+       struct vb2_queue *vq;
+       unsigned int i;
 
-       if (ctx->codec.h265.mv_col_buf_size > 0) {
-               dma_free_attrs(dev->dev, ctx->codec.h265.mv_col_buf_size,
-                              ctx->codec.h265.mv_col_buf,
-                              ctx->codec.h265.mv_col_buf_addr,
-                              DMA_ATTR_NO_KERNEL_MAPPING);
+       vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+
+       for (i = 0; i < vq->num_buffers; i++) {
+               buf = vb2_to_cedrus_buffer(vb2_get_buffer(vq, i));
 
-               ctx->codec.h265.mv_col_buf_size = 0;
+               if (buf->codec.h265.mv_col_buf_size > 0) {
+                       dma_free_attrs(dev->dev,
+                                      buf->codec.h265.mv_col_buf_size,
+                                      buf->codec.h265.mv_col_buf,
+                                      buf->codec.h265.mv_col_buf_dma,
+                                      DMA_ATTR_NO_KERNEL_MAPPING);
+
+                       buf->codec.h265.mv_col_buf_size = 0;
+               }
        }
 
        dma_free_attrs(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE,