930 lines · 28.7 KB · C
RawDownload
// 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.