diff mbox series

[v2,24/34] media: iris: subscribe input and output properties to firmware

Message ID 1702899149-21321-25-git-send-email-quic_dikshita@quicinc.com
State New
Headers show
Series Qualcomm video encoder and decoder driver | expand

Commit Message

Dikshita Agarwal Dec. 18, 2023, 11:32 a.m. UTC
From: Vikash Garodia <quic_vgarodia@quicinc.com>

Driver can subscribe to different properties for which
it expects a response from firmware. Different SOCs
firmware can support different properties which can be
subscribed by driver.
HFI_CMD_SUBSCRIBE_MODE with HFI_MODE_PROPERTY - to subscribe
any property to firmware.

Also, set below mandatory properties on capture plane:
HFI_PROP_COLOR_FORMAT
HFI_PROP_LINEAR_STRIDE_SCANLINE
HFI_PROP_UBWC_STRIDE_SCANLINE.

Signed-off-by: Vikash Garodia <quic_vgarodia@quicinc.com>
Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
---
 .../media/platform/qcom/vcodec/iris/hfi_defines.h  |  31 +++++
 drivers/media/platform/qcom/vcodec/iris/iris_hfi.c |  38 +++++
 drivers/media/platform/qcom/vcodec/iris/iris_hfi.h |   3 +
 .../platform/qcom/vcodec/iris/iris_hfi_packet.c    |  42 ++++++
 .../platform/qcom/vcodec/iris/iris_hfi_packet.h    |   3 +
 .../media/platform/qcom/vcodec/iris/iris_vdec.c    | 154 +++++++++++++++++++++
 .../media/platform/qcom/vcodec/iris/iris_vdec.h    |   2 +
 .../platform/qcom/vcodec/iris/platform_common.h    |   8 ++
 .../platform/qcom/vcodec/iris/platform_sm8550.c    |  29 ++++
 9 files changed, 310 insertions(+)
diff mbox series

Patch

diff --git a/drivers/media/platform/qcom/vcodec/iris/hfi_defines.h b/drivers/media/platform/qcom/vcodec/iris/hfi_defines.h
index ce4eaff..a6078a5 100644
--- a/drivers/media/platform/qcom/vcodec/iris/hfi_defines.h
+++ b/drivers/media/platform/qcom/vcodec/iris/hfi_defines.h
@@ -25,6 +25,29 @@ 
 #define HFI_PROP_UBWC_BANK_SWZL_LEVEL3		0x03000008
 #define HFI_PROP_UBWC_BANK_SPREADING		0x03000009
 
+enum hfi_property_mode_type {
+	HFI_MODE_NONE					= 0x00000000,
+	HFI_MODE_PORT_SETTINGS_CHANGE			= 0x00000001,
+	HFI_MODE_PROPERTY				= 0x00000002,
+};
+
+#define HFI_CMD_SUBSCRIBE_MODE		0x0100000B
+
+enum hfi_color_format {
+	HFI_COLOR_FMT_OPAQUE        = 0,
+	HFI_COLOR_FMT_NV12          = 1,
+	HFI_COLOR_FMT_NV12_UBWC     = 2,
+	HFI_COLOR_FMT_P010          = 3,
+	HFI_COLOR_FMT_TP10_UBWC     = 4,
+	HFI_COLOR_FMT_RGBA8888      = 5,
+	HFI_COLOR_FMT_RGBA8888_UBWC = 6,
+	HFI_COLOR_FMT_NV21          = 7,
+};
+
+#define HFI_PROP_COLOR_FORMAT			0x03000101
+
+#define HFI_PROP_LINEAR_STRIDE_SCANLINE		0x03000104
+
 #define HFI_PROP_PROFILE			0x03000107
 
 #define HFI_PROP_LEVEL				0x03000108
@@ -49,10 +72,18 @@ 
 
 #define HFI_PROP_DECODE_ORDER_OUTPUT		0x0300015b
 
+#define HFI_PROP_PICTURE_TYPE			0x03000162
+
 #define HFI_PROP_DEC_DEFAULT_HEADER		0x03000168
 
 #define HFI_PROP_DEC_START_FROM_RAP_FRAME	0x03000169
 
+#define HFI_PROP_NO_OUTPUT			0x0300016a
+
+#define HFI_PROP_DPB_LIST			0x0300017A
+
+#define HFI_PROP_UBWC_STRIDE_SCANLINE		0x03000190
+
 #define HFI_PROP_COMV_BUFFER_COUNT		0x03000193
 
 #define HFI_SYS_ERROR_WD_TIMEOUT		0x05000001
diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_hfi.c b/drivers/media/platform/qcom/vcodec/iris/iris_hfi.c
index 8f1e456..d15ce5a 100644
--- a/drivers/media/platform/qcom/vcodec/iris/iris_hfi.c
+++ b/drivers/media/platform/qcom/vcodec/iris/iris_hfi.c
@@ -219,6 +219,44 @@  int iris_hfi_session_open(struct iris_inst *inst)
 	return ret;
 }
 
+int iris_hfi_session_subscribe_mode(struct iris_inst *inst,
+				    u32 cmd, u32 plane, u32 payload_type,
+				    void *payload, u32 payload_size)
+{
+	struct iris_core *core;
+	int ret;
+
+	if (!inst->packet)
+		return -EINVAL;
+
+	core = inst->core;
+	mutex_lock(&core->lock);
+
+	if (!validate_session(core, inst)) {
+		ret = -EINVAL;
+		goto unlock;
+	}
+
+	ret = hfi_packet_session_command(inst,
+					 cmd,
+					 (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
+					 HFI_HOST_FLAGS_INTR_REQUIRED),
+					 get_hfi_port(plane),
+					 inst->session_id,
+					 payload_type,
+					 payload,
+					 payload_size);
+	if (ret)
+		goto unlock;
+
+	ret = iris_hfi_queue_cmd_write(inst->core, inst->packet);
+
+unlock:
+	mutex_unlock(&core->lock);
+
+	return ret;
+}
+
 int iris_hfi_session_close(struct iris_inst *inst)
 {
 	struct iris_core *core;
diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_hfi.h b/drivers/media/platform/qcom/vcodec/iris/iris_hfi.h
index ca2339e..d6b3fca 100644
--- a/drivers/media/platform/qcom/vcodec/iris/iris_hfi.h
+++ b/drivers/media/platform/qcom/vcodec/iris/iris_hfi.h
@@ -13,6 +13,9 @@  int iris_hfi_core_init(struct iris_core *core);
 int iris_hfi_core_deinit(struct iris_core *core);
 int iris_hfi_session_open(struct iris_inst *inst);
 int iris_hfi_session_close(struct iris_inst *inst);
+int iris_hfi_session_subscribe_mode(struct iris_inst *inst,
+				    u32 cmd, u32 plane, u32 payload_type,
+				    void *payload, u32 payload_size);
 int iris_hfi_set_property(struct iris_inst *inst,
 			  u32 packet_type, u32 flag, u32 plane, u32 payload_type,
 			  void *payload, u32 payload_size);
diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_hfi_packet.c b/drivers/media/platform/qcom/vcodec/iris/iris_hfi_packet.c
index a3544d8..d4cdfcf 100644
--- a/drivers/media/platform/qcom/vcodec/iris/iris_hfi_packet.c
+++ b/drivers/media/platform/qcom/vcodec/iris/iris_hfi_packet.c
@@ -34,6 +34,24 @@  u32 get_hfi_port_from_buffer_type(enum iris_buffer_type buffer_type)
 	return hfi_port;
 }
 
+u32 get_hfi_port(u32 plane)
+{
+	u32 hfi_port = HFI_PORT_NONE;
+
+	switch (plane) {
+	case INPUT_MPLANE:
+		hfi_port = HFI_PORT_BITSTREAM;
+		break;
+	case OUTPUT_MPLANE:
+		hfi_port = HFI_PORT_RAW;
+		break;
+	default:
+		break;
+	}
+
+	return hfi_port;
+}
+
 static u32 hfi_buf_type_from_driver(enum iris_buffer_type buffer_type)
 {
 	switch (buffer_type) {
@@ -58,6 +76,30 @@  static u32 hfi_buf_type_from_driver(enum iris_buffer_type buffer_type)
 	}
 }
 
+u32 get_hfi_colorformat(u32 colorformat)
+{
+	u32 hfi_colorformat = HFI_COLOR_FMT_NV12_UBWC;
+
+	switch (colorformat) {
+	case V4L2_PIX_FMT_NV12:
+		hfi_colorformat = HFI_COLOR_FMT_NV12;
+		break;
+	case V4L2_PIX_FMT_QC08C:
+		hfi_colorformat = HFI_COLOR_FMT_NV12_UBWC;
+		break;
+	case V4L2_PIX_FMT_QC10C:
+		hfi_colorformat = HFI_COLOR_FMT_TP10_UBWC;
+		break;
+	case V4L2_PIX_FMT_NV21:
+		hfi_colorformat = HFI_COLOR_FMT_NV21;
+		break;
+	default:
+		break;
+	}
+
+	return hfi_colorformat;
+}
+
 int get_hfi_buffer(struct iris_buffer *buffer, struct hfi_buffer *buf)
 {
 	memset(buf, 0, sizeof(*buf));
diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_hfi_packet.h b/drivers/media/platform/qcom/vcodec/iris/iris_hfi_packet.h
index bf18553..4276d6d 100644
--- a/drivers/media/platform/qcom/vcodec/iris/iris_hfi_packet.h
+++ b/drivers/media/platform/qcom/vcodec/iris/iris_hfi_packet.h
@@ -81,6 +81,9 @@  enum hfi_packet_port_type {
 
 u32 get_hfi_port_from_buffer_type(enum iris_buffer_type buffer_type);
 int get_hfi_buffer(struct iris_buffer *buffer, struct hfi_buffer *buf);
+u32 get_hfi_colorformat(u32 colorformat);
+u32 get_hfi_port(u32 plane);
+
 int hfi_packet_sys_init(struct iris_core *core,
 			u8 *pkt, u32 pkt_size);
 int hfi_packet_image_version(struct iris_core *core,
diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_vdec.c b/drivers/media/platform/qcom/vcodec/iris/iris_vdec.c
index 64067d5..7d16c96 100644
--- a/drivers/media/platform/qcom/vcodec/iris/iris_vdec.c
+++ b/drivers/media/platform/qcom/vcodec/iris/iris_vdec.c
@@ -5,10 +5,13 @@ 
 
 #include <media/v4l2-event.h>
 
+#include "hfi_defines.h"
 #include "iris_buffer.h"
 #include "iris_common.h"
 #include "iris_ctrls.h"
 #include "iris_helpers.h"
+#include "iris_hfi.h"
+#include "iris_hfi_packet.h"
 #include "iris_vdec.h"
 
 static int vdec_codec_change(struct iris_inst *inst, u32 v4l2_codec)
@@ -329,3 +332,154 @@  int vdec_subscribe_event(struct iris_inst *inst, const struct v4l2_event_subscri
 
 	return ret;
 }
+
+int vdec_subscribe_property(struct iris_inst *inst, u32 plane)
+{
+	const u32 *subcribe_prop = NULL;
+	u32 subscribe_prop_size = 0;
+	struct iris_core *core;
+	u32 payload[32] = {0};
+	u32 i;
+
+	core = inst->core;
+
+	payload[0] = HFI_MODE_PROPERTY;
+
+	if (plane == INPUT_MPLANE) {
+		subscribe_prop_size = core->platform_data->dec_input_prop_size;
+		subcribe_prop = core->platform_data->dec_input_prop;
+	} else if (plane == OUTPUT_MPLANE) {
+		if (inst->codec == H264) {
+			subscribe_prop_size = core->platform_data->dec_output_prop_size_avc;
+			subcribe_prop = core->platform_data->dec_output_prop_avc;
+		} else if (inst->codec == HEVC) {
+			subscribe_prop_size = core->platform_data->dec_output_prop_size_hevc;
+			subcribe_prop = core->platform_data->dec_output_prop_hevc;
+		} else if (inst->codec == VP9) {
+			subscribe_prop_size = core->platform_data->dec_output_prop_size_vp9;
+			subcribe_prop = core->platform_data->dec_output_prop_vp9;
+		} else {
+			return -EINVAL;
+		}
+	} else {
+		return -EINVAL;
+	}
+
+	for (i = 0; i < subscribe_prop_size; i++)
+		payload[i + 1] = subcribe_prop[i];
+
+	return iris_hfi_session_subscribe_mode(inst,
+					HFI_CMD_SUBSCRIBE_MODE,
+					plane,
+					HFI_PAYLOAD_U32_ARRAY,
+					&payload[0],
+					(subscribe_prop_size + 1) * sizeof(u32));
+}
+
+static int vdec_set_colorformat(struct iris_inst *inst)
+{
+	u32 hfi_colorformat;
+	u32 pixelformat;
+
+	pixelformat = inst->fmt_dst->fmt.pix_mp.pixelformat;
+	hfi_colorformat = get_hfi_colorformat(pixelformat);
+
+	return iris_hfi_set_property(inst,
+					 HFI_PROP_COLOR_FORMAT,
+					 HFI_HOST_FLAGS_NONE,
+					 get_hfi_port(OUTPUT_MPLANE),
+					 HFI_PAYLOAD_U32,
+					 &hfi_colorformat,
+					 sizeof(u32));
+}
+
+static int vdec_set_linear_stride_scanline(struct iris_inst *inst)
+{
+	u32 stride_y, scanline_y, stride_uv, scanline_uv;
+	u32 pixelformat;
+	u32 payload[2];
+
+	pixelformat = inst->fmt_dst->fmt.pix_mp.pixelformat;
+
+	if (!is_linear_colorformat(pixelformat))
+		return 0;
+
+	stride_y = inst->fmt_dst->fmt.pix_mp.width;
+	scanline_y = inst->fmt_dst->fmt.pix_mp.height;
+	stride_uv = stride_y;
+	scanline_uv = scanline_y / 2;
+
+	payload[0] = stride_y << 16 | scanline_y;
+	payload[1] = stride_uv << 16 | scanline_uv;
+
+	return iris_hfi_set_property(inst,
+					 HFI_PROP_LINEAR_STRIDE_SCANLINE,
+					 HFI_HOST_FLAGS_NONE,
+					 get_hfi_port(OUTPUT_MPLANE),
+					 HFI_PAYLOAD_U64,
+					 &payload,
+					 sizeof(u64));
+}
+
+static int vdec_set_ubwc_stride_scanline(struct iris_inst *inst)
+{
+	u32 meta_stride_y, meta_scanline_y, meta_stride_uv, meta_scanline_uv;
+	u32 stride_y, scanline_y, stride_uv, scanline_uv;
+	u32 pix_fmt, width, height;
+	u32 payload[4];
+
+	pix_fmt = inst->fmt_dst->fmt.pix_mp.pixelformat;
+	width = inst->fmt_dst->fmt.pix_mp.width;
+	height = inst->fmt_dst->fmt.pix_mp.height;
+
+	if (is_linear_colorformat(pix_fmt))
+		return 0;
+
+	if (pix_fmt == V4L2_PIX_FMT_QC08C) {
+		stride_y = ALIGN(width, 128);
+		scanline_y = ALIGN(height, 32);
+		stride_uv = ALIGN(width, 128);
+		scanline_uv = ALIGN((height + 1) >> 1, 32);
+		meta_stride_y = ALIGN(DIV_ROUND_UP(width, 32), 64);
+		meta_scanline_y = ALIGN(DIV_ROUND_UP(height, 8), 16);
+		meta_stride_uv = ALIGN(DIV_ROUND_UP((width + 1) >> 1, 16), 64);
+		meta_scanline_uv = ALIGN(DIV_ROUND_UP((height + 1) >> 1, 8), 16);
+	} else {
+		stride_y = ALIGN(ALIGN(width, 192) * 4 / 3, 256);
+		scanline_y = ALIGN(height, 16);
+		stride_uv = ALIGN(ALIGN(width, 192) * 4 / 3, 256);
+		scanline_uv = ALIGN((height + 1) >> 1, 16);
+		meta_stride_y = ALIGN(DIV_ROUND_UP(width, 48), 64);
+		meta_scanline_y = ALIGN(DIV_ROUND_UP(height, 4), 16);
+		meta_stride_uv = ALIGN(DIV_ROUND_UP((width + 1) >> 1, 24), 64);
+		meta_scanline_uv = ALIGN(DIV_ROUND_UP((height + 1) >> 1, 4), 16);
+	}
+
+	payload[0] = stride_y << 16 | scanline_y;
+	payload[1] = stride_uv << 16 | scanline_uv;
+	payload[2] = meta_stride_y << 16 | meta_scanline_y;
+	payload[3] = meta_stride_uv << 16 | meta_scanline_uv;
+
+	return iris_hfi_set_property(inst,
+				     HFI_PROP_UBWC_STRIDE_SCANLINE,
+				     HFI_HOST_FLAGS_NONE,
+				     get_hfi_port(OUTPUT_MPLANE),
+				     HFI_PAYLOAD_U32_ARRAY,
+				     &payload[0],
+				     sizeof(u32) * 4);
+}
+
+int vdec_set_output_property(struct iris_inst *inst)
+{
+	int ret;
+
+	ret = vdec_set_colorformat(inst);
+	if (ret)
+		return ret;
+
+	ret = vdec_set_linear_stride_scanline(inst);
+	if (ret)
+		return ret;
+
+	return vdec_set_ubwc_stride_scanline(inst);
+}
diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_vdec.h b/drivers/media/platform/qcom/vcodec/iris/iris_vdec.h
index a2f159d..6b0306c 100644
--- a/drivers/media/platform/qcom/vcodec/iris/iris_vdec.h
+++ b/drivers/media/platform/qcom/vcodec/iris/iris_vdec.h
@@ -14,5 +14,7 @@  int vdec_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f);
 int vdec_try_fmt(struct iris_inst *inst, struct v4l2_format *f);
 int vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f);
 int vdec_subscribe_event(struct iris_inst *inst, const struct v4l2_event_subscription *sub);
+int vdec_subscribe_property(struct iris_inst *inst, u32 plane);
+int vdec_set_output_property(struct iris_inst *inst);
 
 #endif
diff --git a/drivers/media/platform/qcom/vcodec/iris/platform_common.h b/drivers/media/platform/qcom/vcodec/iris/platform_common.h
index abd11fa..fc12bde 100644
--- a/drivers/media/platform/qcom/vcodec/iris/platform_common.h
+++ b/drivers/media/platform/qcom/vcodec/iris/platform_common.h
@@ -206,6 +206,14 @@  struct platform_data {
 	u32 core_data_size;
 	struct plat_inst_cap *inst_cap_data;
 	u32 inst_cap_data_size;
+	const u32 *dec_input_prop;
+	unsigned int dec_input_prop_size;
+	const u32 *dec_output_prop_avc;
+	unsigned int dec_output_prop_size_avc;
+	const u32 *dec_output_prop_hevc;
+	unsigned int dec_output_prop_size_hevc;
+	const u32 *dec_output_prop_vp9;
+	unsigned int dec_output_prop_size_vp9;
 };
 
 int init_platform(struct iris_core *core);
diff --git a/drivers/media/platform/qcom/vcodec/iris/platform_sm8550.c b/drivers/media/platform/qcom/vcodec/iris/platform_sm8550.c
index 85bc677..6a4bfa3 100644
--- a/drivers/media/platform/qcom/vcodec/iris/platform_sm8550.c
+++ b/drivers/media/platform/qcom/vcodec/iris/platform_sm8550.c
@@ -382,6 +382,26 @@  static struct format_capability format_data_sm8550 = {
 	.color_format_info_size = ARRAY_SIZE(color_format_data_sm8550),
 };
 
+static const u32 sm8550_vdec_input_properties[] = {
+	HFI_PROP_NO_OUTPUT,
+};
+
+static const u32 sm8550_vdec_output_properties_avc[] = {
+	HFI_PROP_PICTURE_TYPE,
+	HFI_PROP_DPB_LIST,
+	HFI_PROP_CABAC_SESSION,
+};
+
+static const u32 sm8550_vdec_output_properties_hevc[] = {
+	HFI_PROP_PICTURE_TYPE,
+	HFI_PROP_DPB_LIST,
+};
+
+static const u32 sm8550_vdec_output_properties_vp9[] = {
+	HFI_PROP_PICTURE_TYPE,
+	HFI_PROP_DPB_LIST,
+};
+
 struct platform_data sm8550_data = {
 	.bus_tbl = sm8550_bus_table,
 	.bus_tbl_size = ARRAY_SIZE(sm8550_bus_table),
@@ -409,4 +429,13 @@  struct platform_data sm8550_data = {
 	.inst_cap_data_size = ARRAY_SIZE(instance_cap_data_sm8550),
 	.ubwc_config = ubwc_config_sm8550,
 	.format_data = &format_data_sm8550,
+
+	.dec_input_prop = sm8550_vdec_input_properties,
+	.dec_input_prop_size = ARRAY_SIZE(sm8550_vdec_input_properties),
+	.dec_output_prop_avc = sm8550_vdec_output_properties_avc,
+	.dec_output_prop_size_avc = ARRAY_SIZE(sm8550_vdec_output_properties_avc),
+	.dec_output_prop_hevc = sm8550_vdec_output_properties_hevc,
+	.dec_output_prop_size_hevc = ARRAY_SIZE(sm8550_vdec_output_properties_hevc),
+	.dec_output_prop_vp9 = sm8550_vdec_output_properties_vp9,
+	.dec_output_prop_size_vp9 = ARRAY_SIZE(sm8550_vdec_output_properties_vp9),
 };