diff mbox series

[15/33] iris: add vidc buffer files

Message ID 1690550624-14642-16-git-send-email-quic_vgarodia@quicinc.com
State New
Headers show
Series Qualcomm video decoder/encoder driver | expand

Commit Message

Vikash Garodia July 28, 2023, 1:23 p.m. UTC
This implements the size and count calcualtions of
different types of buffers for encoder and decoder.

Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
Signed-off-by: Vikash Garodia <quic_vgarodia@quicinc.com>
---
 .../platform/qcom/iris/vidc/inc/msm_vidc_buffer.h  |  32 +++
 .../platform/qcom/iris/vidc/src/msm_vidc_buffer.c  | 290 +++++++++++++++++++++
 2 files changed, 322 insertions(+)
 create mode 100644 drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_buffer.h
 create mode 100644 drivers/media/platform/qcom/iris/vidc/src/msm_vidc_buffer.c
diff mbox series

Patch

diff --git a/drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_buffer.h b/drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_buffer.h
new file mode 100644
index 0000000..0fffcf0
--- /dev/null
+++ b/drivers/media/platform/qcom/iris/vidc/inc/msm_vidc_buffer.h
@@ -0,0 +1,32 @@ 
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef __H_MSM_VIDC_BUFFER_H__
+#define __H_MSM_VIDC_BUFFER_H__
+
+#include "msm_vidc_inst.h"
+
+#define MIN_DEC_INPUT_BUFFERS  4
+#define MIN_DEC_OUTPUT_BUFFERS 4
+
+#define MIN_ENC_INPUT_BUFFERS  4
+#define MIN_ENC_OUTPUT_BUFFERS 4
+
+#define DCVS_ENC_EXTRA_INPUT_BUFFERS  4
+#define DCVS_DEC_EXTRA_OUTPUT_BUFFERS 4
+
+u32 msm_vidc_input_min_count(struct msm_vidc_inst *inst);
+u32 msm_vidc_output_min_count(struct msm_vidc_inst *inst);
+u32 msm_vidc_input_extra_count(struct msm_vidc_inst *inst);
+u32 msm_vidc_output_extra_count(struct msm_vidc_inst *inst);
+u32 msm_vidc_internal_buffer_count(struct msm_vidc_inst *inst,
+				   enum msm_vidc_buffer_type buffer_type);
+u32 msm_vidc_decoder_input_size(struct msm_vidc_inst *inst);
+u32 msm_vidc_decoder_output_size(struct msm_vidc_inst *inst);
+u32 msm_vidc_encoder_input_size(struct msm_vidc_inst *inst);
+u32 msm_vidc_encoder_output_size(struct msm_vidc_inst *inst);
+
+#endif // __H_MSM_VIDC_BUFFER_H__
diff --git a/drivers/media/platform/qcom/iris/vidc/src/msm_vidc_buffer.c b/drivers/media/platform/qcom/iris/vidc/src/msm_vidc_buffer.c
new file mode 100644
index 0000000..a2a0eea
--- /dev/null
+++ b/drivers/media/platform/qcom/iris/vidc/src/msm_vidc_buffer.c
@@ -0,0 +1,290 @@ 
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include "msm_media_info.h"
+#include "msm_vidc_buffer.h"
+#include "msm_vidc_core.h"
+#include "msm_vidc_debug.h"
+#include "msm_vidc_driver.h"
+#include "msm_vidc_inst.h"
+#include "msm_vidc_internal.h"
+
+/* Generic function for all targets. Not being used for iris2 */
+u32 msm_vidc_input_min_count(struct msm_vidc_inst *inst)
+{
+	u32 input_min_count = 0;
+	u32 hb_enh_layer = 0;
+
+	if (is_decode_session(inst)) {
+		input_min_count = MIN_DEC_INPUT_BUFFERS;
+	} else if (is_encode_session(inst)) {
+		input_min_count = MIN_ENC_INPUT_BUFFERS;
+		if (is_hierb_type_requested(inst)) {
+			hb_enh_layer =
+				inst->capabilities[ENH_LAYER_COUNT].value;
+			if (inst->codec == MSM_VIDC_H264 &&
+			    !inst->capabilities[LAYER_ENABLE].value) {
+				hb_enh_layer = 0;
+			}
+			if (hb_enh_layer)
+				input_min_count = (1 << hb_enh_layer) + 2;
+		}
+	} else {
+		i_vpr_e(inst, "%s: invalid domain %d\n",
+			__func__, inst->domain);
+		return 0;
+	}
+
+	return input_min_count;
+}
+
+u32 msm_vidc_output_min_count(struct msm_vidc_inst *inst)
+{
+	u32 output_min_count;
+
+	if (!is_decode_session(inst) && !is_encode_session(inst))
+		return 0;
+
+	if (is_encode_session(inst))
+		return MIN_ENC_OUTPUT_BUFFERS;
+
+	/* decoder handling below */
+	/* fw_min_count > 0 indicates reconfig event has already arrived */
+	if (inst->fw_min_count) {
+		if (is_split_mode_enabled(inst) &&
+		    inst->codec == MSM_VIDC_VP9) {
+			/*
+			 * return opb min buffer count as min(4, fw_min_count)
+			 * fw min count is used for dpb min count
+			 */
+			return min_t(u32, 4, inst->fw_min_count);
+		} else {
+			return inst->fw_min_count;
+		}
+	}
+
+	/* initial handling before reconfig event arrived */
+	switch (inst->codec) {
+	case MSM_VIDC_H264:
+	case MSM_VIDC_HEVC:
+		output_min_count = 4;
+		break;
+	case MSM_VIDC_VP9:
+		output_min_count = 9;
+		break;
+	default:
+		output_min_count = 4;
+		break;
+	}
+
+	return output_min_count;
+}
+
+u32 msm_vidc_input_extra_count(struct msm_vidc_inst *inst)
+{
+	u32 count = 0;
+	struct msm_vidc_core *core;
+
+	core = inst->core;
+
+	if (is_decode_session(inst)) {
+		/*
+		 * if decode batching enabled, ensure minimum batch size
+		 * count of input buffers present on input port
+		 */
+		if (core->capabilities[DECODE_BATCH].value &&
+		    inst->decode_batch.enable) {
+			if (inst->buffers.input.min_count < inst->decode_batch.size) {
+				count = inst->decode_batch.size -
+					inst->buffers.input.min_count;
+			}
+		}
+	} else if (is_encode_session(inst)) {
+		/* add dcvs buffers, if platform supports dcvs */
+		if (core->capabilities[DCVS].value)
+			count = DCVS_ENC_EXTRA_INPUT_BUFFERS;
+	}
+
+	return count;
+}
+
+u32 msm_vidc_output_extra_count(struct msm_vidc_inst *inst)
+{
+	u32 count = 0;
+	struct msm_vidc_core *core;
+
+	core = inst->core;
+
+	if (is_decode_session(inst)) {
+		/* add dcvs buffers, if platform supports dcvs */
+		if (core->capabilities[DCVS].value)
+			count = DCVS_DEC_EXTRA_OUTPUT_BUFFERS;
+		/*
+		 * if decode batching enabled, ensure minimum batch size
+		 * count of extra output buffers added on output port
+		 */
+		if (core->capabilities[DECODE_BATCH].value &&
+		    inst->decode_batch.enable &&
+			count < inst->decode_batch.size)
+			count = inst->decode_batch.size;
+	}
+
+	return count;
+}
+
+u32 msm_vidc_internal_buffer_count(struct msm_vidc_inst *inst,
+				   enum msm_vidc_buffer_type buffer_type)
+{
+	u32 count = 0;
+
+	if (is_encode_session(inst))
+		return 1;
+
+	if (is_decode_session(inst)) {
+		if (buffer_type == MSM_VIDC_BUF_BIN ||
+		    buffer_type == MSM_VIDC_BUF_LINE ||
+		    buffer_type == MSM_VIDC_BUF_PERSIST) {
+			count = 1;
+		} else if (buffer_type == MSM_VIDC_BUF_COMV ||
+			buffer_type == MSM_VIDC_BUF_NON_COMV) {
+			if (inst->codec == MSM_VIDC_H264 ||
+			    inst->codec == MSM_VIDC_HEVC)
+				count = 1;
+			else
+				count = 0;
+		} else {
+			i_vpr_e(inst, "%s: unsupported buffer type %s\n",
+				__func__, buf_name(buffer_type));
+			count = 0;
+		}
+	}
+
+	return count;
+}
+
+u32 msm_vidc_decoder_input_size(struct msm_vidc_inst *inst)
+{
+	u32 frame_size, num_mbs;
+	u32 div_factor = 1;
+	u32 base_res_mbs = NUM_MBS_4k;
+	struct v4l2_format *f;
+	u32 bitstream_size_overwrite = 0;
+	enum msm_vidc_codec_type codec;
+
+	bitstream_size_overwrite =
+		inst->capabilities[BITSTREAM_SIZE_OVERWRITE].value;
+	if (bitstream_size_overwrite) {
+		frame_size = bitstream_size_overwrite;
+		i_vpr_h(inst, "client configured bitstream buffer size %d\n",
+			frame_size);
+		return frame_size;
+	}
+
+	/*
+	 * Decoder input size calculation:
+	 * For 8k resolution, buffer size is calculated as 8k mbs / 4 and
+	 * for 8k cases we expect width/height to be set always.
+	 * In all other cases, buffer size is calculated as
+	 * 4k mbs for VP8/VP9 and 4k / 2 for remaining codecs.
+	 */
+	f = &inst->fmts[INPUT_PORT];
+	codec = v4l2_codec_to_driver(inst, f->fmt.pix_mp.pixelformat, __func__);
+	num_mbs = msm_vidc_get_mbs_per_frame(inst);
+	if (num_mbs > NUM_MBS_4k) {
+		div_factor = 4;
+		base_res_mbs = inst->capabilities[MBPF].value;
+	} else {
+		base_res_mbs = NUM_MBS_4k;
+		if (codec == MSM_VIDC_VP9)
+			div_factor = 1;
+		else
+			div_factor = 2;
+	}
+
+	frame_size = base_res_mbs * MB_SIZE_IN_PIXEL * 3 / 2 / div_factor;
+
+	 /* multiply by 10/8 (1.25) to get size for 10 bit case */
+	if (codec == MSM_VIDC_VP9 || codec == MSM_VIDC_HEVC)
+		frame_size = frame_size + (frame_size >> 2);
+
+	i_vpr_h(inst, "set input buffer size to %d\n", frame_size);
+
+	return ALIGN(frame_size, SZ_4K);
+}
+
+u32 msm_vidc_decoder_output_size(struct msm_vidc_inst *inst)
+{
+	u32 size;
+	struct v4l2_format *f;
+	enum msm_vidc_colorformat_type colorformat;
+
+	f = &inst->fmts[OUTPUT_PORT];
+	colorformat = v4l2_colorformat_to_driver(inst, f->fmt.pix_mp.pixelformat,
+						 __func__);
+	size = video_buffer_size(colorformat, f->fmt.pix_mp.width,
+				 f->fmt.pix_mp.height, true);
+	return size;
+}
+
+u32 msm_vidc_encoder_input_size(struct msm_vidc_inst *inst)
+{
+	u32 size;
+	struct v4l2_format *f;
+	u32 width, height;
+	enum msm_vidc_colorformat_type colorformat;
+
+	f = &inst->fmts[INPUT_PORT];
+	width = f->fmt.pix_mp.width;
+	height = f->fmt.pix_mp.height;
+	colorformat = v4l2_colorformat_to_driver(inst, f->fmt.pix_mp.pixelformat,
+						 __func__);
+	size = video_buffer_size(colorformat, width, height, true);
+	return size;
+}
+
+u32 msm_vidc_encoder_output_size(struct msm_vidc_inst *inst)
+{
+	u32 frame_size;
+	u32 mbs_per_frame;
+	u32 width, height;
+	struct v4l2_format *f;
+	enum msm_vidc_codec_type codec;
+
+	f = &inst->fmts[OUTPUT_PORT];
+	codec = v4l2_codec_to_driver(inst, f->fmt.pix_mp.pixelformat, __func__);
+	/*
+	 * Encoder output size calculation: 32 Align width/height
+	 * For resolution <= 480x360p : YUVsize * 2
+	 * For resolution > 360p & <= 4K : YUVsize / 2
+	 * For resolution > 4k : YUVsize / 4
+	 * Initially frame_size = YUVsize * 2;
+	 */
+
+	width = ALIGN(f->fmt.pix_mp.width, BUFFER_ALIGNMENT_SIZE(32));
+	height = ALIGN(f->fmt.pix_mp.height, BUFFER_ALIGNMENT_SIZE(32));
+	mbs_per_frame = NUM_MBS_PER_FRAME(width, height);
+	frame_size = (width * height * 3);
+
+	/* Image session: 2 x yuv size */
+	if (inst->capabilities[BITRATE_MODE].value == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ)
+		goto skip_calc;
+
+	if (mbs_per_frame <= NUM_MBS_360P)
+		(void)frame_size; /* Default frame_size = YUVsize * 2 */
+	else if (mbs_per_frame <= NUM_MBS_4k)
+		frame_size = frame_size >> 2;
+	else
+		frame_size = frame_size >> 3;
+
+skip_calc:
+	/* multiply by 10/8 (1.25) to get size for 10 bit case */
+	if (codec == MSM_VIDC_HEVC)
+		frame_size = frame_size + (frame_size >> 2);
+
+	frame_size = ALIGN(frame_size, SZ_4K);
+
+	return frame_size;
+}