// SPDX-License-Identifier: GPL-2.0-only/* * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. */ #include <media/v4l2-event.h>#include <media/v4l2-mem2mem.h> #include "iris_buffer.h"#include "iris_instance.h"#include "iris_power.h"#include "iris_vpu_buffer.h" #define PIXELS_4K 4096#define MAX_WIDTH 4096#define MAX_HEIGHT 2304#define Y_STRIDE_ALIGN 128#define Y_STRIDE_ALIGN_P010 256#define UV_STRIDE_ALIGN 128#define UV_STRIDE_ALIGN_P010 256#define Y_SCANLINE_ALIGN 32#define Y_SCANLINE_ALIGN_QC10C 16#define UV_SCANLINE_ALIGN 16#define UV_SCANLINE_ALIGN_QC08C 32#define META_STRIDE_ALIGNED 64#define META_SCANLINE_ALIGNED 16#define NUM_MBS_4K (DIV_ROUND_UP(MAX_WIDTH, 16) * DIV_ROUND_UP(MAX_HEIGHT, 16)) /* * NV12: * YUV 4:2:0 image with a plane of 8 bit Y samples followed * by an interleaved U/V plane containing 8 bit 2x2 subsampled * colour difference samples. * * <-Y/UV_Stride (aligned to 128)-> * <------- Width -------> * Y Y Y Y Y Y Y Y Y Y Y Y . . . . ^ ^ * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | | * Y Y Y Y Y Y Y Y Y Y Y Y . . . . Height | * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | y_scanlines (aligned to 32) * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | | * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | | * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | | * Y Y Y Y Y Y Y Y Y Y Y Y . . . . V | * . . . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . . . V * U V U V U V U V U V U V . . . . ^ * U V U V U V U V U V U V . . . . | * U V U V U V U V U V U V . . . . | * U V U V U V U V U V U V . . . . uv_scanlines (aligned to 16) * . . . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . . . V * . . . . . . . . . . . . . . . . --> Buffer size aligned to 4K * * y_stride : Width aligned to 128 * uv_stride : Width aligned to 128 * y_scanlines: Height aligned to 32 * uv_scanlines: Height/2 aligned to 16 * Total size = align((y_stride * y_scanlines * + uv_stride * uv_scanlines , 4096) * * Note: All the alignments are hardware requirements. */static u32 iris_yuv_buffer_size_nv12(struct iris_inst *inst){ u32 y_plane, uv_plane, y_stride, uv_stride, y_scanlines, uv_scanlines; struct v4l2_format *f; if (inst->domain == DECODER) f = inst->fmt_dst; else f = inst->fmt_src; y_stride = ALIGN(f->fmt.pix_mp.width, Y_STRIDE_ALIGN); uv_stride = ALIGN(f->fmt.pix_mp.width, UV_STRIDE_ALIGN); y_scanlines = ALIGN(f->fmt.pix_mp.height, Y_SCANLINE_ALIGN); uv_scanlines = ALIGN((f->fmt.pix_mp.height + 1) >> 1, UV_SCANLINE_ALIGN); y_plane = y_stride * y_scanlines; uv_plane = uv_stride * uv_scanlines; return ALIGN(y_plane + uv_plane, PIXELS_4K);} /* * P010: * YUV 4:2:0 image with a plane of 10 bit Y samples followed * by an interleaved U/V plane containing 10 bit 2x2 subsampled * colour difference samples. * * <-Y/UV_Stride (aligned to 256)-> * <----- Width*2 -------> * Y Y Y Y Y Y Y Y Y Y Y Y . . . . ^ ^ * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | | * Y Y Y Y Y Y Y Y Y Y Y Y . . . . Height | * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | y_scanlines (aligned to 32) * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | | * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | | * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | | * Y Y Y Y Y Y Y Y Y Y Y Y . . . . V | * . . . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . . . V * U V U V U V U V U V U V . . . . ^ * U V U V U V U V U V U V . . . . | * U V U V U V U V U V U V . . . . | * U V U V U V U V U V U V . . . . uv_scanlines (aligned to 16) * . . . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . . . V * . . . . . . . . . . . . . . . . --> Buffer size aligned to 4K * * y_stride : Width*2 aligned to 256 * uv_stride : Width*2 aligned to 256 * y_scanlines: Height aligned to 32 * uv_scanlines: Height/2 aligned to 16 * Total size = align((y_stride * y_scanlines * + uv_stride * uv_scanlines , 4096) * * Note: All the alignments are hardware requirements. */static u32 iris_yuv_buffer_size_p010(struct iris_inst *inst){ u32 y_plane, uv_plane, y_stride, uv_stride, y_scanlines, uv_scanlines; struct v4l2_format *f; if (inst->domain == DECODER) f = inst->fmt_dst; else f = inst->fmt_src; y_stride = ALIGN(f->fmt.pix_mp.width * 2, Y_STRIDE_ALIGN_P010); uv_stride = ALIGN(f->fmt.pix_mp.width * 2, UV_STRIDE_ALIGN_P010); y_scanlines = ALIGN(f->fmt.pix_mp.height, Y_SCANLINE_ALIGN); uv_scanlines = ALIGN((f->fmt.pix_mp.height + 1) >> 1, UV_SCANLINE_ALIGN); y_plane = y_stride * y_scanlines; uv_plane = uv_stride * uv_scanlines; return ALIGN(y_plane + uv_plane, PIXELS_4K);} /* * QC08C: * Compressed Macro-tile format for NV12. * Contains 4 planes in the following order - * (A) Y_Meta_Plane * (B) Y_UBWC_Plane * (C) UV_Meta_Plane * (D) UV_UBWC_Plane * * Y_Meta_Plane consists of meta information to decode compressed * tile data in Y_UBWC_Plane. * Y_UBWC_Plane consists of Y data in compressed macro-tile format. * UBWC decoder block will use the Y_Meta_Plane data together with * Y_UBWC_Plane data to produce loss-less uncompressed 8 bit Y samples. * * UV_Meta_Plane consists of meta information to decode compressed * tile data in UV_UBWC_Plane. * UV_UBWC_Plane consists of UV data in compressed macro-tile format. * UBWC decoder block will use UV_Meta_Plane data together with * UV_UBWC_Plane data to produce loss-less uncompressed 8 bit 2x2 * subsampled color difference samples. * * Each tile in Y_UBWC_Plane/UV_UBWC_Plane is independently decodable * and randomly accessible. There is no dependency between tiles. * * <----- y_meta_stride ----> (aligned to 64) * <-------- Width ------> * M M M M M M M M M M M M . . ^ ^ * M M M M M M M M M M M M . . | | * M M M M M M M M M M M M . . Height | * M M M M M M M M M M M M . . | y_meta_scanlines (aligned to 16) * M M M M M M M M M M M M . . | | * M M M M M M M M M M M M . . | | * M M M M M M M M M M M M . . | | * M M M M M M M M M M M M . . V | * . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . -------> Buffer size aligned to 4k * . . . . . . . . . . . . . . V * <--Compressed tile y_stride---> (aligned to 128) * <------- Width -------> * Y* Y* Y* Y* Y* Y* Y* Y* . . . . ^ ^ * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | | * Y* Y* Y* Y* Y* Y* Y* Y* . . . . Height | * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | Macro_tile y_scanlines (aligned to 32) * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | | * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | | * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | | * Y* Y* Y* Y* Y* Y* Y* Y* . . . . V | * . . . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . . . -------> Buffer size aligned to 4k * . . . . . . . . . . . . . . . . V * <----- uv_meta_stride ----> (aligned to 64) * M M M M M M M M M M M M . . ^ * M M M M M M M M M M M M . . | * M M M M M M M M M M M M . . | * M M M M M M M M M M M M . . uv_meta_scanlines (aligned to 16) * . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . V * . . . . . . . . . . . . . . -------> Buffer size aligned to 4k * <--Compressed tile uv_stride---> (aligned to 128) * U* V* U* V* U* V* U* V* . . . . ^ * U* V* U* V* U* V* U* V* . . . . | * U* V* U* V* U* V* U* V* . . . . | * U* V* U* V* U* V* U* V* . . . . uv_scanlines (aligned to 32) * . . . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . . . V * . . . . . . . . . . . . . . . . -------> Buffer size aligned to 4k * * y_stride: width aligned to 128 * uv_stride: width aligned to 128 * y_scanlines: height aligned to 32 * uv_scanlines: height aligned to 32 * y_plane: buffer size aligned to 4096 * uv_plane: buffer size aligned to 4096 * y_meta_stride: width aligned to 64 * y_meta_scanlines: height aligned to 16 * y_meta_plane: buffer size aligned to 4096 * uv_meta_stride: width aligned to 64 * uv_meta_scanlines: height aligned to 16 * uv_meta_plane: buffer size aligned to 4096 * * Total size = align( y_plane + uv_plane + * y_meta_plane + uv_meta_plane, 4096) * * Note: All the alignments are hardware requirements. */static u32 iris_yuv_buffer_size_qc08c(struct iris_inst *inst){ u32 y_plane, uv_plane, y_stride, uv_stride; u32 uv_meta_stride, uv_meta_plane; u32 y_meta_stride, y_meta_plane; struct v4l2_format *f = NULL; if (inst->domain == DECODER) f = inst->fmt_dst; else f = inst->fmt_src; y_meta_stride = ALIGN(DIV_ROUND_UP(f->fmt.pix_mp.width, META_STRIDE_ALIGNED >> 1), META_STRIDE_ALIGNED); y_meta_plane = y_meta_stride * ALIGN(DIV_ROUND_UP(f->fmt.pix_mp.height, META_SCANLINE_ALIGNED >> 1), META_SCANLINE_ALIGNED); y_meta_plane = ALIGN(y_meta_plane, PIXELS_4K); y_stride = ALIGN(f->fmt.pix_mp.width, Y_STRIDE_ALIGN); y_plane = ALIGN(y_stride * ALIGN(f->fmt.pix_mp.height, Y_SCANLINE_ALIGN), PIXELS_4K); uv_meta_stride = ALIGN(DIV_ROUND_UP(f->fmt.pix_mp.width / 2, META_STRIDE_ALIGNED >> 2), META_STRIDE_ALIGNED); uv_meta_plane = uv_meta_stride * ALIGN(DIV_ROUND_UP(f->fmt.pix_mp.height / 2, META_SCANLINE_ALIGNED >> 1), META_SCANLINE_ALIGNED); uv_meta_plane = ALIGN(uv_meta_plane, PIXELS_4K); uv_stride = ALIGN(f->fmt.pix_mp.width, UV_STRIDE_ALIGN); uv_plane = ALIGN(uv_stride * ALIGN(f->fmt.pix_mp.height / 2, UV_SCANLINE_ALIGN_QC08C), PIXELS_4K); return ALIGN(y_meta_plane + y_plane + uv_meta_plane + uv_plane, PIXELS_4K);} /* * QC10C: * UBWC-compressed format for P010. * Contains 4 planes in the following order - * (A) Y_Meta_Plane * (B) Y_UBWC_Plane * (C) UV_Meta_Plane * (D) UV_UBWC_Plane * * Y_Meta_Plane consists of meta information to decode compressed * tile data in Y_UBWC_Plane. * Y_UBWC_Plane consists of Y data in compressed macro-tile format. * UBWC decoder block will use the Y_Meta_Plane data together with * Y_UBWC_Plane data to produce loss-less uncompressed 10 bit Y samples. * * UV_Meta_Plane consists of meta information to decode compressed * tile data in UV_UBWC_Plane. * UV_UBWC_Plane consists of UV data in compressed macro-tile format. * UBWC decoder block will use UV_Meta_Plane data together with * UV_UBWC_Plane data to produce loss-less uncompressed 10 bit 2x2 * subsampled color difference samples. * * Each tile in Y_UBWC_Plane/UV_UBWC_Plane is independently decodable * and randomly accessible. There is no dependency between tiles. * * <----- Y Meta stride -----> (aligned to 64) * <-------- Width ----------> (aligned to 48) * M M M M M M M M M M M M . . ^ ^ * M M M M M M M M M M M M . . | | * M M M M M M M M M M M M . . Height | * M M M M M M M M M M M M . . | Meta_Y_Scanlines (aligned to 16) * M M M M M M M M M M M M . . | | * M M M M M M M M M M M M . . | | * M M M M M M M M M M M M . . | | * M M M M M M M M M M M M . . V | * . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . -------> Buffer size aligned to 4k * . . . . . . . . . . . . . . V * <--Compressed tile Y stride --> (aligned to 256) * <------- Width * 4/3 ---------> (aligned to 48) * Y* Y* Y* Y* Y* Y* Y* Y* . . . . ^ ^ * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | | * Y* Y* Y* Y* Y* Y* Y* Y* . . . . Height | * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | Macro_tile_Y_Scanlines (aligned to 16) * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | | * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | | * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | | * Y* Y* Y* Y* Y* Y* Y* Y* . . . . V | * . . . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . . . -------> Buffer size aligned to 4k * . . . . . . . . . . . . . . . . V * <---- UV Meta stride ----> (aligned to 64) * <----- Width / 2 --------> (aligned to 24) * M M M M M M M M M M M M . . ^ ^ * M M M M M M M M M M M M . . | | * M M M M M M M M M M M M . . Height/2 | * M M M M M M M M M M M M . . V M_UV_Scanlines (aligned to 16) * . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . V * . . . . . . . . . . . . . . -------> Buffer size aligned to 4k * <--Compressed tile UV stride--> (aligned to 256) * <------- Width * 4/3 ---------> (aligned to 48) * U* V* U* V* U* V* U* V* . . . . ^ * U* V* U* V* U* V* U* V* . . . . | * U* V* U* V* U* V* U* V* . . . . | * U* V* U* V* U* V* U* V* . . . . UV_Scanlines (aligned to 16) * . . . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . . . V * . . . . . . . . . . . . . . . . -------> Buffer size aligned to 4k * * y_stride: width aligned to 256 * uv_stride: width aligned to 256 * y_scanlines: height aligned to 16 * uv_scanlines: height aligned to 16 * y_plane: buffer size aligned to 4096 * uv_plane: buffer size aligned to 4096 * y_meta_stride: width aligned to 64 * y_meta_scanlines: height aligned to 16 * y_meta_plane: buffer size aligned to 4096 * uv_meta_stride: width aligned to 64 * uv_meta_scanlines: height aligned to 16 * uv_meta_plane: buffer size aligned to 4096 * * Total size = align( y_plane + uv_plane + * y_meta_plane + uv_meta_plane, 4096) * * Note: All the alignments are hardware requirements. */static u32 iris_yuv_buffer_size_qc10c(struct iris_inst *inst){ u32 y_plane, uv_plane, y_stride, uv_stride; u32 uv_meta_stride, uv_meta_plane; u32 y_meta_stride, y_meta_plane; struct v4l2_format *f; if (inst->domain == DECODER) f = inst->fmt_dst; else f = inst->fmt_src; y_meta_stride = ALIGN(DIV_ROUND_UP(f->fmt.pix_mp.width, 48), META_STRIDE_ALIGNED); y_meta_plane = y_meta_stride * ALIGN(DIV_ROUND_UP(f->fmt.pix_mp.height, 4), META_SCANLINE_ALIGNED); y_meta_plane = ALIGN(y_meta_plane, PIXELS_4K); y_stride = ALIGN(f->fmt.pix_mp.width * 4 / 3, Y_STRIDE_ALIGN_P010); y_plane = ALIGN(y_stride * ALIGN(f->fmt.pix_mp.height, Y_SCANLINE_ALIGN_QC10C), PIXELS_4K); uv_meta_stride = ALIGN(DIV_ROUND_UP((f->fmt.pix_mp.width + 1) >> 1, 24), META_STRIDE_ALIGNED); uv_meta_plane = uv_meta_stride * ALIGN(DIV_ROUND_UP((f->fmt.pix_mp.height + 1) >> 1, 4), META_SCANLINE_ALIGNED); uv_meta_plane = ALIGN(uv_meta_plane, PIXELS_4K); uv_stride = ALIGN(f->fmt.pix_mp.width * 4 / 3, UV_STRIDE_ALIGN_P010); uv_plane = ALIGN(uv_stride * ALIGN((f->fmt.pix_mp.height + 1) >> 1, UV_SCANLINE_ALIGN), PIXELS_4K); return ALIGN(y_meta_plane + y_plane + uv_meta_plane + uv_plane, PIXELS_4K);} static u32 iris_dec_bitstream_buffer_size(struct iris_inst *inst){ struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps; u32 base_res_mbs = NUM_MBS_4K; u32 frame_size, num_mbs; u32 div_factor = 2; num_mbs = iris_get_mbpf(inst); if (num_mbs > NUM_MBS_4K) { div_factor = 4; base_res_mbs = caps->max_mbpf; } else { if (inst->codec == V4L2_PIX_FMT_VP9) div_factor = 1; } /* * frame_size = YUVsize / div_factor * where YUVsize = resolution_in_MBs * MBs_in_pixel * 3 / 2 */ frame_size = base_res_mbs * (16 * 16) * 3 / 2 / div_factor; return ALIGN(frame_size, PIXELS_4K);} static u32 iris_enc_bitstream_buffer_size(struct iris_inst *inst){ u32 aligned_width, aligned_height, bitstream_size, yuv_size; int bitrate_mode, frame_rc; struct v4l2_format *f; f = inst->fmt_dst; bitrate_mode = inst->fw_caps[BITRATE_MODE].value; frame_rc = inst->fw_caps[FRAME_RC_ENABLE].value; aligned_width = ALIGN(f->fmt.pix_mp.width, 32); aligned_height = ALIGN(f->fmt.pix_mp.height, 32); bitstream_size = aligned_width * aligned_height * 3; yuv_size = (aligned_width * aligned_height * 3) >> 1; if (aligned_width * aligned_height > (4096 * 2176)) /* bitstream_size = 0.25 * yuv_size; */ bitstream_size = (bitstream_size >> 3); else if (aligned_width * aligned_height > (1280 * 720)) /* bitstream_size = 0.5 * yuv_size; */ bitstream_size = (bitstream_size >> 2); if ((!frame_rc || bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ) && bitstream_size < yuv_size) bitstream_size = (bitstream_size << 1); return ALIGN(bitstream_size, 4096);} int iris_get_buffer_size(struct iris_inst *inst, enum iris_buffer_type buffer_type){ if (inst->domain == DECODER) { switch (buffer_type) { case BUF_INPUT: return iris_dec_bitstream_buffer_size(inst); case BUF_OUTPUT: if (inst->fmt_dst->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_QC08C) return iris_yuv_buffer_size_qc08c(inst); else if (inst->fmt_dst->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_QC10C) return iris_yuv_buffer_size_qc10c(inst); else if (inst->fmt_dst->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_P010) return iris_yuv_buffer_size_p010(inst); else return iris_yuv_buffer_size_nv12(inst); case BUF_DPB: if (iris_fmt_is_10bit(inst->fmt_dst->fmt.pix_mp.pixelformat)) return iris_yuv_buffer_size_qc10c(inst); else return iris_yuv_buffer_size_qc08c(inst); default: return 0; } } else { switch (buffer_type) { case BUF_INPUT: if (inst->fmt_src->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_QC08C) return iris_yuv_buffer_size_qc08c(inst); else return iris_yuv_buffer_size_nv12(inst); case BUF_OUTPUT: return iris_enc_bitstream_buffer_size(inst); default: return 0; } }} static void iris_fill_internal_buf_info(struct iris_inst *inst, enum iris_buffer_type buffer_type){ struct iris_buffers *buffers = &inst->buffers[buffer_type]; buffers->size = inst->core->iris_firmware_desc->get_vpu_buffer_size(inst, buffer_type); buffers->min_count = iris_vpu_buf_count(inst, buffer_type);} static void iris_get_int_buf_tbl(struct iris_inst *inst, u32 plane, const u32 **internal_buf_type, u32 *internal_buffer_count){ const struct iris_firmware_data *firmware_data = inst->core->iris_firmware_data; if (inst->domain == DECODER) {Lines 1–500 of 930. Load more
// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. */ #include <media/v4l2-event.h> #include <media/v4l2-mem2mem.h> #include "iris_buffer.h" #include "iris_instance.h" #include "iris_power.h" #include "iris_vpu_buffer.h" #define PIXELS_4K 4096 #define MAX_WIDTH 4096 #define MAX_HEIGHT 2304 #define Y_STRIDE_ALIGN 128 #define Y_STRIDE_ALIGN_P010 256 #define UV_STRIDE_ALIGN 128 #define UV_STRIDE_ALIGN_P010 256 #define Y_SCANLINE_ALIGN 32 #define Y_SCANLINE_ALIGN_QC10C 16 #define UV_SCANLINE_ALIGN 16 #define UV_SCANLINE_ALIGN_QC08C 32 #define META_STRIDE_ALIGNED 64 #define META_SCANLINE_ALIGNED 16 #define NUM_MBS_4K (DIV_ROUND_UP(MAX_WIDTH, 16) * DIV_ROUND_UP(MAX_HEIGHT, 16)) /* * NV12: * YUV 4:2:0 image with a plane of 8 bit Y samples followed * by an interleaved U/V plane containing 8 bit 2x2 subsampled * colour difference samples. * * <-Y/UV_Stride (aligned to 128)-> * <------- Width -------> * Y Y Y Y Y Y Y Y Y Y Y Y . . . . ^ ^ * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | | * Y Y Y Y Y Y Y Y Y Y Y Y . . . . Height | * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | y_scanlines (aligned to 32) * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | | * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | | * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | | * Y Y Y Y Y Y Y Y Y Y Y Y . . . . V | * . . . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . . . V * U V U V U V U V U V U V . . . . ^ * U V U V U V U V U V U V . . . . | * U V U V U V U V U V U V . . . . | * U V U V U V U V U V U V . . . . uv_scanlines (aligned to 16) * . . . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . . . V * . . . . . . . . . . . . . . . . --> Buffer size aligned to 4K * * y_stride : Width aligned to 128 * uv_stride : Width aligned to 128 * y_scanlines: Height aligned to 32 * uv_scanlines: Height/2 aligned to 16 * Total size = align((y_stride * y_scanlines * + uv_stride * uv_scanlines , 4096) * * Note: All the alignments are hardware requirements. */ static u32 iris_yuv_buffer_size_nv12(struct iris_inst *inst) { u32 y_plane, uv_plane, y_stride, uv_stride, y_scanlines, uv_scanlines; struct v4l2_format *f; if (inst->domain == DECODER) f = inst->fmt_dst; else f = inst->fmt_src; y_stride = ALIGN(f->fmt.pix_mp.width, Y_STRIDE_ALIGN); uv_stride = ALIGN(f->fmt.pix_mp.width, UV_STRIDE_ALIGN); y_scanlines = ALIGN(f->fmt.pix_mp.height, Y_SCANLINE_ALIGN); uv_scanlines = ALIGN((f->fmt.pix_mp.height + 1) >> 1, UV_SCANLINE_ALIGN); y_plane = y_stride * y_scanlines; uv_plane = uv_stride * uv_scanlines; return ALIGN(y_plane + uv_plane, PIXELS_4K); } /* * P010: * YUV 4:2:0 image with a plane of 10 bit Y samples followed * by an interleaved U/V plane containing 10 bit 2x2 subsampled * colour difference samples. * * <-Y/UV_Stride (aligned to 256)-> * <----- Width*2 -------> * Y Y Y Y Y Y Y Y Y Y Y Y . . . . ^ ^ * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | | * Y Y Y Y Y Y Y Y Y Y Y Y . . . . Height | * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | y_scanlines (aligned to 32) * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | | * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | | * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | | * Y Y Y Y Y Y Y Y Y Y Y Y . . . . V | * . . . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . . . V * U V U V U V U V U V U V . . . . ^ * U V U V U V U V U V U V . . . . | * U V U V U V U V U V U V . . . . | * U V U V U V U V U V U V . . . . uv_scanlines (aligned to 16) * . . . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . . . V * . . . . . . . . . . . . . . . . --> Buffer size aligned to 4K * * y_stride : Width*2 aligned to 256 * uv_stride : Width*2 aligned to 256 * y_scanlines: Height aligned to 32 * uv_scanlines: Height/2 aligned to 16 * Total size = align((y_stride * y_scanlines * + uv_stride * uv_scanlines , 4096) * * Note: All the alignments are hardware requirements. */ static u32 iris_yuv_buffer_size_p010(struct iris_inst *inst) { u32 y_plane, uv_plane, y_stride, uv_stride, y_scanlines, uv_scanlines; struct v4l2_format *f; if (inst->domain == DECODER) f = inst->fmt_dst; else f = inst->fmt_src; y_stride = ALIGN(f->fmt.pix_mp.width * 2, Y_STRIDE_ALIGN_P010); uv_stride = ALIGN(f->fmt.pix_mp.width * 2, UV_STRIDE_ALIGN_P010); y_scanlines = ALIGN(f->fmt.pix_mp.height, Y_SCANLINE_ALIGN); uv_scanlines = ALIGN((f->fmt.pix_mp.height + 1) >> 1, UV_SCANLINE_ALIGN); y_plane = y_stride * y_scanlines; uv_plane = uv_stride * uv_scanlines; return ALIGN(y_plane + uv_plane, PIXELS_4K); } /* * QC08C: * Compressed Macro-tile format for NV12. * Contains 4 planes in the following order - * (A) Y_Meta_Plane * (B) Y_UBWC_Plane * (C) UV_Meta_Plane * (D) UV_UBWC_Plane * * Y_Meta_Plane consists of meta information to decode compressed * tile data in Y_UBWC_Plane. * Y_UBWC_Plane consists of Y data in compressed macro-tile format. * UBWC decoder block will use the Y_Meta_Plane data together with * Y_UBWC_Plane data to produce loss-less uncompressed 8 bit Y samples. * * UV_Meta_Plane consists of meta information to decode compressed * tile data in UV_UBWC_Plane. * UV_UBWC_Plane consists of UV data in compressed macro-tile format. * UBWC decoder block will use UV_Meta_Plane data together with * UV_UBWC_Plane data to produce loss-less uncompressed 8 bit 2x2 * subsampled color difference samples. * * Each tile in Y_UBWC_Plane/UV_UBWC_Plane is independently decodable * and randomly accessible. There is no dependency between tiles. * * <----- y_meta_stride ----> (aligned to 64) * <-------- Width ------> * M M M M M M M M M M M M . . ^ ^ * M M M M M M M M M M M M . . | | * M M M M M M M M M M M M . . Height | * M M M M M M M M M M M M . . | y_meta_scanlines (aligned to 16) * M M M M M M M M M M M M . . | | * M M M M M M M M M M M M . . | | * M M M M M M M M M M M M . . | | * M M M M M M M M M M M M . . V | * . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . -------> Buffer size aligned to 4k * . . . . . . . . . . . . . . V * <--Compressed tile y_stride---> (aligned to 128) * <------- Width -------> * Y* Y* Y* Y* Y* Y* Y* Y* . . . . ^ ^ * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | | * Y* Y* Y* Y* Y* Y* Y* Y* . . . . Height | * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | Macro_tile y_scanlines (aligned to 32) * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | | * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | | * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | | * Y* Y* Y* Y* Y* Y* Y* Y* . . . . V | * . . . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . . . -------> Buffer size aligned to 4k * . . . . . . . . . . . . . . . . V * <----- uv_meta_stride ----> (aligned to 64) * M M M M M M M M M M M M . . ^ * M M M M M M M M M M M M . . | * M M M M M M M M M M M M . . | * M M M M M M M M M M M M . . uv_meta_scanlines (aligned to 16) * . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . V * . . . . . . . . . . . . . . -------> Buffer size aligned to 4k * <--Compressed tile uv_stride---> (aligned to 128) * U* V* U* V* U* V* U* V* . . . . ^ * U* V* U* V* U* V* U* V* . . . . | * U* V* U* V* U* V* U* V* . . . . | * U* V* U* V* U* V* U* V* . . . . uv_scanlines (aligned to 32) * . . . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . . . V * . . . . . . . . . . . . . . . . -------> Buffer size aligned to 4k * * y_stride: width aligned to 128 * uv_stride: width aligned to 128 * y_scanlines: height aligned to 32 * uv_scanlines: height aligned to 32 * y_plane: buffer size aligned to 4096 * uv_plane: buffer size aligned to 4096 * y_meta_stride: width aligned to 64 * y_meta_scanlines: height aligned to 16 * y_meta_plane: buffer size aligned to 4096 * uv_meta_stride: width aligned to 64 * uv_meta_scanlines: height aligned to 16 * uv_meta_plane: buffer size aligned to 4096 * * Total size = align( y_plane + uv_plane + * y_meta_plane + uv_meta_plane, 4096) * * Note: All the alignments are hardware requirements. */ static u32 iris_yuv_buffer_size_qc08c(struct iris_inst *inst) { u32 y_plane, uv_plane, y_stride, uv_stride; u32 uv_meta_stride, uv_meta_plane; u32 y_meta_stride, y_meta_plane; struct v4l2_format *f = NULL; if (inst->domain == DECODER) f = inst->fmt_dst; else f = inst->fmt_src; y_meta_stride = ALIGN(DIV_ROUND_UP(f->fmt.pix_mp.width, META_STRIDE_ALIGNED >> 1), META_STRIDE_ALIGNED); y_meta_plane = y_meta_stride * ALIGN(DIV_ROUND_UP(f->fmt.pix_mp.height, META_SCANLINE_ALIGNED >> 1), META_SCANLINE_ALIGNED); y_meta_plane = ALIGN(y_meta_plane, PIXELS_4K); y_stride = ALIGN(f->fmt.pix_mp.width, Y_STRIDE_ALIGN); y_plane = ALIGN(y_stride * ALIGN(f->fmt.pix_mp.height, Y_SCANLINE_ALIGN), PIXELS_4K); uv_meta_stride = ALIGN(DIV_ROUND_UP(f->fmt.pix_mp.width / 2, META_STRIDE_ALIGNED >> 2), META_STRIDE_ALIGNED); uv_meta_plane = uv_meta_stride * ALIGN(DIV_ROUND_UP(f->fmt.pix_mp.height / 2, META_SCANLINE_ALIGNED >> 1), META_SCANLINE_ALIGNED); uv_meta_plane = ALIGN(uv_meta_plane, PIXELS_4K); uv_stride = ALIGN(f->fmt.pix_mp.width, UV_STRIDE_ALIGN); uv_plane = ALIGN(uv_stride * ALIGN(f->fmt.pix_mp.height / 2, UV_SCANLINE_ALIGN_QC08C), PIXELS_4K); return ALIGN(y_meta_plane + y_plane + uv_meta_plane + uv_plane, PIXELS_4K); } /* * QC10C: * UBWC-compressed format for P010. * Contains 4 planes in the following order - * (A) Y_Meta_Plane * (B) Y_UBWC_Plane * (C) UV_Meta_Plane * (D) UV_UBWC_Plane * * Y_Meta_Plane consists of meta information to decode compressed * tile data in Y_UBWC_Plane. * Y_UBWC_Plane consists of Y data in compressed macro-tile format. * UBWC decoder block will use the Y_Meta_Plane data together with * Y_UBWC_Plane data to produce loss-less uncompressed 10 bit Y samples. * * UV_Meta_Plane consists of meta information to decode compressed * tile data in UV_UBWC_Plane. * UV_UBWC_Plane consists of UV data in compressed macro-tile format. * UBWC decoder block will use UV_Meta_Plane data together with * UV_UBWC_Plane data to produce loss-less uncompressed 10 bit 2x2 * subsampled color difference samples. * * Each tile in Y_UBWC_Plane/UV_UBWC_Plane is independently decodable * and randomly accessible. There is no dependency between tiles. * * <----- Y Meta stride -----> (aligned to 64) * <-------- Width ----------> (aligned to 48) * M M M M M M M M M M M M . . ^ ^ * M M M M M M M M M M M M . . | | * M M M M M M M M M M M M . . Height | * M M M M M M M M M M M M . . | Meta_Y_Scanlines (aligned to 16) * M M M M M M M M M M M M . . | | * M M M M M M M M M M M M . . | | * M M M M M M M M M M M M . . | | * M M M M M M M M M M M M . . V | * . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . -------> Buffer size aligned to 4k * . . . . . . . . . . . . . . V * <--Compressed tile Y stride --> (aligned to 256) * <------- Width * 4/3 ---------> (aligned to 48) * Y* Y* Y* Y* Y* Y* Y* Y* . . . . ^ ^ * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | | * Y* Y* Y* Y* Y* Y* Y* Y* . . . . Height | * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | Macro_tile_Y_Scanlines (aligned to 16) * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | | * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | | * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | | * Y* Y* Y* Y* Y* Y* Y* Y* . . . . V | * . . . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . . . -------> Buffer size aligned to 4k * . . . . . . . . . . . . . . . . V * <---- UV Meta stride ----> (aligned to 64) * <----- Width / 2 --------> (aligned to 24) * M M M M M M M M M M M M . . ^ ^ * M M M M M M M M M M M M . . | | * M M M M M M M M M M M M . . Height/2 | * M M M M M M M M M M M M . . V M_UV_Scanlines (aligned to 16) * . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . V * . . . . . . . . . . . . . . -------> Buffer size aligned to 4k * <--Compressed tile UV stride--> (aligned to 256) * <------- Width * 4/3 ---------> (aligned to 48) * U* V* U* V* U* V* U* V* . . . . ^ * U* V* U* V* U* V* U* V* . . . . | * U* V* U* V* U* V* U* V* . . . . | * U* V* U* V* U* V* U* V* . . . . UV_Scanlines (aligned to 16) * . . . . . . . . . . . . . . . . | * . . . . . . . . . . . . . . . . V * . . . . . . . . . . . . . . . . -------> Buffer size aligned to 4k * * y_stride: width aligned to 256 * uv_stride: width aligned to 256 * y_scanlines: height aligned to 16 * uv_scanlines: height aligned to 16 * y_plane: buffer size aligned to 4096 * uv_plane: buffer size aligned to 4096 * y_meta_stride: width aligned to 64 * y_meta_scanlines: height aligned to 16 * y_meta_plane: buffer size aligned to 4096 * uv_meta_stride: width aligned to 64 * uv_meta_scanlines: height aligned to 16 * uv_meta_plane: buffer size aligned to 4096 * * Total size = align( y_plane + uv_plane + * y_meta_plane + uv_meta_plane, 4096) * * Note: All the alignments are hardware requirements. */ static u32 iris_yuv_buffer_size_qc10c(struct iris_inst *inst) { u32 y_plane, uv_plane, y_stride, uv_stride; u32 uv_meta_stride, uv_meta_plane; u32 y_meta_stride, y_meta_plane; struct v4l2_format *f; if (inst->domain == DECODER) f = inst->fmt_dst; else f = inst->fmt_src; y_meta_stride = ALIGN(DIV_ROUND_UP(f->fmt.pix_mp.width, 48), META_STRIDE_ALIGNED); y_meta_plane = y_meta_stride * ALIGN(DIV_ROUND_UP(f->fmt.pix_mp.height, 4), META_SCANLINE_ALIGNED); y_meta_plane = ALIGN(y_meta_plane, PIXELS_4K); y_stride = ALIGN(f->fmt.pix_mp.width * 4 / 3, Y_STRIDE_ALIGN_P010); y_plane = ALIGN(y_stride * ALIGN(f->fmt.pix_mp.height, Y_SCANLINE_ALIGN_QC10C), PIXELS_4K); uv_meta_stride = ALIGN(DIV_ROUND_UP((f->fmt.pix_mp.width + 1) >> 1, 24), META_STRIDE_ALIGNED); uv_meta_plane = uv_meta_stride * ALIGN(DIV_ROUND_UP((f->fmt.pix_mp.height + 1) >> 1, 4), META_SCANLINE_ALIGNED); uv_meta_plane = ALIGN(uv_meta_plane, PIXELS_4K); uv_stride = ALIGN(f->fmt.pix_mp.width * 4 / 3, UV_STRIDE_ALIGN_P010); uv_plane = ALIGN(uv_stride * ALIGN((f->fmt.pix_mp.height + 1) >> 1, UV_SCANLINE_ALIGN), PIXELS_4K); return ALIGN(y_meta_plane + y_plane + uv_meta_plane + uv_plane, PIXELS_4K); } static u32 iris_dec_bitstream_buffer_size(struct iris_inst *inst) { struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps; u32 base_res_mbs = NUM_MBS_4K; u32 frame_size, num_mbs; u32 div_factor = 2; num_mbs = iris_get_mbpf(inst); if (num_mbs > NUM_MBS_4K) { div_factor = 4; base_res_mbs = caps->max_mbpf; } else { if (inst->codec == V4L2_PIX_FMT_VP9) div_factor = 1; } /* * frame_size = YUVsize / div_factor * where YUVsize = resolution_in_MBs * MBs_in_pixel * 3 / 2 */ frame_size = base_res_mbs * (16 * 16) * 3 / 2 / div_factor; return ALIGN(frame_size, PIXELS_4K); } static u32 iris_enc_bitstream_buffer_size(struct iris_inst *inst) { u32 aligned_width, aligned_height, bitstream_size, yuv_size; int bitrate_mode, frame_rc; struct v4l2_format *f; f = inst->fmt_dst; bitrate_mode = inst->fw_caps[BITRATE_MODE].value; frame_rc = inst->fw_caps[FRAME_RC_ENABLE].value; aligned_width = ALIGN(f->fmt.pix_mp.width, 32); aligned_height = ALIGN(f->fmt.pix_mp.height, 32); bitstream_size = aligned_width * aligned_height * 3; yuv_size = (aligned_width * aligned_height * 3) >> 1; if (aligned_width * aligned_height > (4096 * 2176)) /* bitstream_size = 0.25 * yuv_size; */ bitstream_size = (bitstream_size >> 3); else if (aligned_width * aligned_height > (1280 * 720)) /* bitstream_size = 0.5 * yuv_size; */ bitstream_size = (bitstream_size >> 2); if ((!frame_rc || bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ) && bitstream_size < yuv_size) bitstream_size = (bitstream_size << 1); return ALIGN(bitstream_size, 4096); } int iris_get_buffer_size(struct iris_inst *inst, enum iris_buffer_type buffer_type) { if (inst->domain == DECODER) { switch (buffer_type) { case BUF_INPUT: return iris_dec_bitstream_buffer_size(inst); case BUF_OUTPUT: if (inst->fmt_dst->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_QC08C) return iris_yuv_buffer_size_qc08c(inst); else if (inst->fmt_dst->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_QC10C) return iris_yuv_buffer_size_qc10c(inst); else if (inst->fmt_dst->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_P010) return iris_yuv_buffer_size_p010(inst); else return iris_yuv_buffer_size_nv12(inst); case BUF_DPB: if (iris_fmt_is_10bit(inst->fmt_dst->fmt.pix_mp.pixelformat)) return iris_yuv_buffer_size_qc10c(inst); else return iris_yuv_buffer_size_qc08c(inst); default: return 0; } } else { switch (buffer_type) { case BUF_INPUT: if (inst->fmt_src->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_QC08C) return iris_yuv_buffer_size_qc08c(inst); else return iris_yuv_buffer_size_nv12(inst); case BUF_OUTPUT: return iris_enc_bitstream_buffer_size(inst); default: return 0; } } } static void iris_fill_internal_buf_info(struct iris_inst *inst, enum iris_buffer_type buffer_type) { struct iris_buffers *buffers = &inst->buffers[buffer_type]; buffers->size = inst->core->iris_firmware_desc->get_vpu_buffer_size(inst, buffer_type); buffers->min_count = iris_vpu_buf_count(inst, buffer_type); } static void iris_get_int_buf_tbl(struct iris_inst *inst, u32 plane, const u32 **internal_buf_type, u32 *internal_buffer_count) { const struct iris_firmware_data *firmware_data = inst->core->iris_firmware_data; if (inst->domain == DECODER) {