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

From: Dikshita Agarwal
Date: Mon Dec 18 2023 - 06:40:06 EST


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@xxxxxxxxxxx>
---
.../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 --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,
--
2.7.4