diff mbox series

[v2,19/34] media: iris: implement HFI to queue and release buffers

Message ID 1702899149-21321-20-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
Introduce and implement HFIs to queue and release
all input, output and internal buffers to/from firmware.

HFI_CMD_BUFFER - to submit the buffer to firmware.
HFI_CMD_BUFFER with HFI_BUF_HOST_FLAG_RELEASE - to request
firmware to release the buffer.

Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
---
 .../media/platform/qcom/vcodec/iris/hfi_defines.h  | 25 +++++++
 drivers/media/platform/qcom/vcodec/iris/iris_hfi.c | 85 ++++++++++++++++++++++
 drivers/media/platform/qcom/vcodec/iris/iris_hfi.h |  4 +
 .../platform/qcom/vcodec/iris/iris_hfi_packet.c    | 78 ++++++++++++++++++++
 .../platform/qcom/vcodec/iris/iris_hfi_packet.h    | 15 ++++
 5 files changed, 207 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 9dd5f11..c044f78 100644
--- a/drivers/media/platform/qcom/vcodec/iris/hfi_defines.h
+++ b/drivers/media/platform/qcom/vcodec/iris/hfi_defines.h
@@ -13,6 +13,7 @@ 
 #define HFI_CMD_INIT				0x01000001
 #define HFI_CMD_OPEN				0x01000003
 #define HFI_CMD_CLOSE				0x01000004
+#define HFI_CMD_BUFFER				0x01000009
 
 #define HFI_PROP_IMAGE_VERSION			0x03000001
 
@@ -60,4 +61,28 @@  struct hfi_debug_header {
 	u32   reserved[2];
 };
 
+enum hfi_buffer_type {
+	HFI_BUFFER_BITSTREAM		= 0x00000001,
+	HFI_BUFFER_RAW			= 0x00000002,
+	HFI_BUFFER_METADATA		= 0x00000003,
+	HFI_BUFFER_SUBCACHE		= 0x00000004,
+	HFI_BUFFER_PARTIAL_DATA		= 0x00000005,
+	HFI_BUFFER_DPB			= 0x00000006,
+	HFI_BUFFER_BIN			= 0x00000007,
+	HFI_BUFFER_LINE			= 0x00000008,
+	HFI_BUFFER_ARP			= 0x00000009,
+	HFI_BUFFER_COMV			= 0x0000000A,
+	HFI_BUFFER_NON_COMV		= 0x0000000B,
+	HFI_BUFFER_PERSIST		= 0x0000000C,
+	HFI_BUFFER_VPSS			= 0x0000000D,
+};
+
+enum hfi_buffer_host_flags {
+	HFI_BUF_HOST_FLAG_NONE			= 0x00000000,
+	HFI_BUF_HOST_FLAG_RELEASE		= 0x00000001,
+	HFI_BUF_HOST_FLAG_READONLY		= 0x00000010,
+	HFI_BUF_HOST_FLAG_CODEC_CONFIG		= 0x00000100,
+	HFI_BUF_HOST_FLAGS_CB_NON_SECURE	= 0x00000200,
+};
+
 #endif
diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_hfi.c b/drivers/media/platform/qcom/vcodec/iris/iris_hfi.c
index 24ddb98..8f1e456 100644
--- a/drivers/media/platform/qcom/vcodec/iris/iris_hfi.c
+++ b/drivers/media/platform/qcom/vcodec/iris/iris_hfi.c
@@ -309,3 +309,88 @@  int iris_hfi_set_property(struct iris_inst *inst,
 
 	return ret;
 }
+
+int iris_hfi_queue_buffer(struct iris_inst *inst,
+			  struct iris_buffer *buffer)
+{
+	struct hfi_buffer hfi_buffer;
+	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 = get_hfi_buffer(buffer, &hfi_buffer);
+	if (ret)
+		goto unlock;
+
+	ret = hfi_packet_session_command(inst,
+					 HFI_CMD_BUFFER,
+					 HFI_HOST_FLAGS_INTR_REQUIRED,
+					 get_hfi_port_from_buffer_type(buffer->type),
+					 inst->session_id,
+					 HFI_PAYLOAD_STRUCTURE,
+					 &hfi_buffer,
+					 sizeof(hfi_buffer));
+	if (ret)
+		goto unlock;
+
+	ret = iris_hfi_queue_cmd_write(inst->core, inst->packet);
+
+unlock:
+	mutex_unlock(&core->lock);
+
+	return ret;
+}
+
+int iris_hfi_release_buffer(struct iris_inst *inst,
+			    struct iris_buffer *buffer)
+{
+	struct hfi_buffer hfi_buffer;
+	struct iris_core *core;
+	int ret;
+
+	if (!inst->packet || !buffer)
+		return -EINVAL;
+
+	core = inst->core;
+	mutex_lock(&core->lock);
+
+	if (!validate_session(core, inst)) {
+		ret = -EINVAL;
+		goto unlock;
+	}
+
+	ret = get_hfi_buffer(buffer, &hfi_buffer);
+	if (ret)
+		goto unlock;
+
+	hfi_buffer.flags |= HFI_BUF_HOST_FLAG_RELEASE;
+
+	ret = hfi_packet_session_command(inst,
+					 HFI_CMD_BUFFER,
+					 (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
+					 HFI_HOST_FLAGS_INTR_REQUIRED),
+					 get_hfi_port_from_buffer_type(buffer->type),
+					 inst->session_id,
+					 HFI_PAYLOAD_STRUCTURE,
+					 &hfi_buffer,
+					 sizeof(hfi_buffer));
+	if (ret)
+		goto unlock;
+
+	ret = iris_hfi_queue_cmd_write(inst->core, inst->packet);
+
+unlock:
+	mutex_unlock(&core->lock);
+
+	return ret;
+}
diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_hfi.h b/drivers/media/platform/qcom/vcodec/iris/iris_hfi.h
index bf991bb..4aefdc4 100644
--- a/drivers/media/platform/qcom/vcodec/iris/iris_hfi.h
+++ b/drivers/media/platform/qcom/vcodec/iris/iris_hfi.h
@@ -19,5 +19,9 @@  int iris_hfi_set_property(struct iris_inst *inst,
 
 irqreturn_t iris_hfi_isr(int irq, void *data);
 irqreturn_t iris_hfi_isr_handler(int irq, void *data);
+int iris_hfi_queue_buffer(struct iris_inst *inst,
+			  struct iris_buffer *buffer);
+int iris_hfi_release_buffer(struct iris_inst *inst,
+			    struct iris_buffer *buffer);
 
 #endif
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 749d978..a3544d8 100644
--- a/drivers/media/platform/qcom/vcodec/iris/iris_hfi_packet.c
+++ b/drivers/media/platform/qcom/vcodec/iris/iris_hfi_packet.c
@@ -4,9 +4,87 @@ 
  */
 
 #include "iris_core.h"
+#include "iris_helpers.h"
 #include "iris_hfi_packet.h"
 #include "hfi_defines.h"
 
+u32 get_hfi_port_from_buffer_type(enum iris_buffer_type buffer_type)
+{
+	u32 hfi_port = HFI_PORT_NONE;
+
+	switch (buffer_type) {
+	case BUF_INPUT:
+	case BUF_BIN:
+	case BUF_COMV:
+	case BUF_NON_COMV:
+	case BUF_LINE:
+		hfi_port = HFI_PORT_BITSTREAM;
+		break;
+	case BUF_OUTPUT:
+	case BUF_DPB:
+		hfi_port = HFI_PORT_RAW;
+		break;
+	case BUF_PERSIST:
+		hfi_port = HFI_PORT_NONE;
+		break;
+	default:
+		break;
+	}
+
+	return hfi_port;
+}
+
+static u32 hfi_buf_type_from_driver(enum iris_buffer_type buffer_type)
+{
+	switch (buffer_type) {
+	case BUF_INPUT:
+		return HFI_BUFFER_BITSTREAM;
+	case BUF_OUTPUT:
+		return HFI_BUFFER_RAW;
+	case BUF_BIN:
+		return HFI_BUFFER_BIN;
+	case BUF_COMV:
+		return HFI_BUFFER_COMV;
+	case BUF_NON_COMV:
+		return HFI_BUFFER_NON_COMV;
+	case BUF_LINE:
+		return HFI_BUFFER_LINE;
+	case BUF_DPB:
+		return HFI_BUFFER_DPB;
+	case BUF_PERSIST:
+		return HFI_BUFFER_PERSIST;
+	default:
+		return 0;
+	}
+}
+
+int get_hfi_buffer(struct iris_buffer *buffer, struct hfi_buffer *buf)
+{
+	memset(buf, 0, sizeof(*buf));
+	buf->type = hfi_buf_type_from_driver(buffer->type);
+	buf->index = buffer->index;
+	buf->base_address = buffer->device_addr;
+	buf->addr_offset = 0;
+	buf->buffer_size = buffer->buffer_size;
+	/*
+	 * for decoder input buffers, firmware (BSE HW) needs 256 aligned
+	 * buffer size otherwise it will truncate or ignore the data after 256
+	 * aligned size which may lead to error concealment
+	 */
+	if (buffer->type == BUF_INPUT)
+		buf->buffer_size = ALIGN(buffer->buffer_size, 256);
+	buf->data_offset = buffer->data_offset;
+	buf->data_size = buffer->data_size;
+	if (buffer->attr & BUF_ATTR_READ_ONLY)
+		buf->flags |= HFI_BUF_HOST_FLAG_READONLY;
+	if (buffer->attr & BUF_ATTR_PENDING_RELEASE)
+		buf->flags |= HFI_BUF_HOST_FLAG_RELEASE;
+	buf->flags |= HFI_BUF_HOST_FLAGS_CB_NON_SECURE;
+	buf->timestamp = buffer->timestamp;
+
+	return 0;
+}
+
 static int hfi_create_header(u8 *packet, u32 packet_size, u32 session_id,
 			     u32 header_id)
 {
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 bea7ed9..bf18553 100644
--- a/drivers/media/platform/qcom/vcodec/iris/iris_hfi_packet.h
+++ b/drivers/media/platform/qcom/vcodec/iris/iris_hfi_packet.h
@@ -27,6 +27,19 @@  struct hfi_packet {
 	u32 reserved[2];
 };
 
+struct hfi_buffer {
+	u32 type;
+	u32 index;
+	u64 base_address;
+	u32 addr_offset;
+	u32 buffer_size;
+	u32 data_offset;
+	u32 data_size;
+	u64 timestamp;
+	u32 flags;
+	u32 reserved[5];
+};
+
 enum hfi_packet_host_flags {
 	HFI_HOST_FLAGS_NONE			= 0x00000000,
 	HFI_HOST_FLAGS_INTR_REQUIRED		= 0x00000001,
@@ -66,6 +79,8 @@  enum hfi_packet_port_type {
 	HFI_PORT_RAW		= 0x00000002,
 };
 
+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);
 int hfi_packet_sys_init(struct iris_core *core,
 			u8 *pkt, u32 pkt_size);
 int hfi_packet_image_version(struct iris_core *core,