@@ -1,9 +1,10 @@
-iris-objs += ../hfi_queue.o ../firmware.o
+iris-objs += ../hfi_queue.o ../firmware.o ../buffers.o
iris-objs += iris_probe.o \
iris_state.o \
iris_core.o \
iris_vidc.o \
+ iris_vb2.o \
iris_vdec.o \
iris_state.o \
iris_ctrls.o \
@@ -11,6 +12,7 @@ iris-objs += iris_probe.o \
iris_hfi.o \
iris_hfi_response.o \
iris_hfi_packet.o \
+ iris_buffer.o \
resources.o \
vpu_common.o \
vpu_iris3.o \
new file mode 100644
@@ -0,0 +1,179 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include "../buffers.h"
+#include "iris_buffer.h"
+#include "iris_helpers.h"
+#include "iris_instance.h"
+
+static int input_min_count(struct iris_inst *inst)
+{
+ return MIN_BUFFERS;
+}
+
+static int output_min_count(struct iris_inst *inst)
+{
+ int output_min_count;
+
+ switch (inst->codec) {
+ case H264:
+ case HEVC:
+ output_min_count = 4;
+ break;
+ case VP9:
+ output_min_count = 9;
+ break;
+ default:
+ output_min_count = 4;
+ break;
+ }
+
+ return output_min_count;
+}
+
+int iris_get_buf_min_count(struct iris_inst *inst,
+ enum iris_buffer_type buffer_type)
+{
+ switch (buffer_type) {
+ case BUF_INPUT:
+ return input_min_count(inst);
+ case BUF_OUTPUT:
+ return output_min_count(inst);
+ default:
+ return 0;
+ }
+}
+
+static u32 input_buffer_size(struct iris_inst *inst)
+{
+ u32 base_res_mbs = NUM_MBS_4k;
+ u32 frame_size, num_mbs;
+ struct v4l2_format *f;
+ u32 div_factor = 1;
+ u32 codec;
+
+ f = inst->fmt_src;
+ codec = f->fmt.pix_mp.pixelformat;
+
+ num_mbs = get_mbpf(inst);
+ if (num_mbs > NUM_MBS_4k) {
+ div_factor = 4;
+ base_res_mbs = inst->cap[MBPF].value;
+ } else {
+ base_res_mbs = NUM_MBS_4k;
+ if (codec == V4L2_PIX_FMT_VP9)
+ div_factor = 1;
+ else
+ div_factor = 2;
+ }
+
+ frame_size = base_res_mbs * MB_IN_PIXEL * 3 / 2 / div_factor;
+
+ /* multiply by 10/8 (1.25) to get size for 10 bit case */
+ if (codec == V4L2_PIX_FMT_VP9 || codec == V4L2_PIX_FMT_HEVC)
+ frame_size = frame_size + (frame_size >> 2);
+
+ return ALIGN(frame_size, SZ_4K);
+}
+
+static u32 output_buffer_size(struct iris_inst *inst)
+{
+ struct v4l2_format *f;
+ u32 size;
+
+ f = inst->fmt_dst;
+
+ size = video_raw_buffer_size(f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.width,
+ f->fmt.pix_mp.height);
+ return size;
+}
+
+int iris_get_buffer_size(struct iris_inst *inst,
+ enum iris_buffer_type buffer_type)
+{
+ switch (buffer_type) {
+ case BUF_INPUT:
+ return input_buffer_size(inst);
+ case BUF_OUTPUT:
+ return output_buffer_size(inst);
+ default:
+ return 0;
+ }
+}
+
+struct iris_buffers *iris_get_buffer_list(struct iris_inst *inst,
+ enum iris_buffer_type buffer_type)
+{
+ switch (buffer_type) {
+ case BUF_INPUT:
+ return &inst->buffers.input;
+ case BUF_OUTPUT:
+ return &inst->buffers.output;
+ case BUF_READ_ONLY:
+ return &inst->buffers.read_only;
+ case BUF_BIN:
+ return &inst->buffers.bin;
+ case BUF_ARP:
+ return &inst->buffers.arp;
+ case BUF_COMV:
+ return &inst->buffers.comv;
+ case BUF_NON_COMV:
+ return &inst->buffers.non_comv;
+ case BUF_LINE:
+ return &inst->buffers.line;
+ case BUF_DPB:
+ return &inst->buffers.dpb;
+ case BUF_PERSIST:
+ return &inst->buffers.persist;
+ case BUF_VPSS:
+ return &inst->buffers.vpss;
+ default:
+ return NULL;
+ }
+}
+
+int iris_allocate_buffers(struct iris_inst *inst,
+ enum iris_buffer_type buf_type,
+ u32 num_buffers)
+{
+ struct iris_buffer *buf = NULL;
+ struct iris_buffers *buffers;
+ int idx = 0;
+
+ buffers = iris_get_buffer_list(inst, buf_type);
+ if (!buffers)
+ return -EINVAL;
+
+ for (idx = 0; idx < num_buffers; idx++) {
+ buf = kzalloc(sizeof(*buf), GFP_KERNEL);
+ if (!buf)
+ return -EINVAL;
+
+ INIT_LIST_HEAD(&buf->list);
+ list_add_tail(&buf->list, &buffers->list);
+ buf->type = buf_type;
+ buf->index = idx;
+ }
+
+ return 0;
+}
+
+int iris_free_buffers(struct iris_inst *inst,
+ enum iris_buffer_type buf_type)
+{
+ struct iris_buffer *buf, *dummy;
+ struct iris_buffers *buffers;
+
+ buffers = iris_get_buffer_list(inst, buf_type);
+ if (!buffers)
+ return -EINVAL;
+
+ list_for_each_entry_safe(buf, dummy, &buffers->list, list) {
+ list_del_init(&buf->list);
+ kfree(buf);
+ }
+
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef _IRIS_BUFFER_H_
+#define _IRIS_BUFFER_H_
+
+#define MIN_BUFFERS 4
+
+#include "iris_common.h"
+
+struct iris_inst;
+
+struct iris_buffers {
+ struct list_head list; // list of "struct iris_buffer"
+ u32 min_count;
+ u32 actual_count;
+ u32 size;
+ bool reuse;
+};
+
+struct iris_buffers_info {
+ struct iris_buffers input;
+ struct iris_buffers output;
+ struct iris_buffers read_only;
+ struct iris_buffers bin;
+ struct iris_buffers arp;
+ struct iris_buffers comv;
+ struct iris_buffers non_comv;
+ struct iris_buffers line;
+ struct iris_buffers dpb;
+ struct iris_buffers persist;
+ struct iris_buffers vpss;
+};
+
+int iris_get_buf_min_count(struct iris_inst *inst,
+ enum iris_buffer_type buffer_type);
+int iris_get_buffer_size(struct iris_inst *inst,
+ enum iris_buffer_type buffer_type);
+struct iris_buffers *iris_get_buffer_list(struct iris_inst *inst,
+ enum iris_buffer_type buffer_type);
+int iris_allocate_buffers(struct iris_inst *inst,
+ enum iris_buffer_type buf_type,
+ u32 num_buffers);
+int iris_free_buffers(struct iris_inst *inst,
+ enum iris_buffer_type buf_type);
+
+#endif
@@ -5,6 +5,7 @@
#ifndef _IRIS_COMMON_H_
#define _IRIS_COMMON_H_
+#include <media/v4l2-dev.h>
#include <media/v4l2-device.h>
#include <media/v4l2-event.h>
#include <media/v4l2-ioctl.h>
@@ -14,7 +15,31 @@
#define OUTPUT_MPLANE V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
#define DEFAULT_WIDTH 320
#define DEFAULT_HEIGHT 240
-#define DEFAULT_BUF_SIZE 115200
+
+#define MB_IN_PIXEL (16 * 16)
+
+#define NUM_MBS_4k (((4096 + 15) >> 4) * ((2304 + 15) >> 4))
+
+enum codec_type {
+ H264 = BIT(0),
+ HEVC = BIT(1),
+ VP9 = BIT(2),
+};
+
+enum colorformat_type {
+ FMT_NONE = 0,
+ FMT_NV12C = BIT(0),
+ FMT_NV12 = BIT(1),
+ FMT_NV21 = BIT(2),
+ FMT_TP10C = BIT(3),
+};
+
+struct rect_desc {
+ u32 left;
+ u32 top;
+ u32 width;
+ u32 height;
+};
enum signal_session_response {
SIGNAL_CMD_STOP_INPUT = 0,
@@ -23,4 +48,48 @@ enum signal_session_response {
MAX_SIGNAL,
};
+enum iris_buffer_type {
+ BUF_NONE,
+ BUF_INPUT,
+ BUF_OUTPUT,
+ BUF_READ_ONLY,
+ BUF_BIN,
+ BUF_ARP,
+ BUF_COMV,
+ BUF_NON_COMV,
+ BUF_LINE,
+ BUF_DPB,
+ BUF_PERSIST,
+ BUF_VPSS,
+};
+
+enum iris_buffer_attributes {
+ BUF_ATTR_DEFERRED = BIT(0),
+ BUF_ATTR_READ_ONLY = BIT(1),
+ BUF_ATTR_PENDING_RELEASE = BIT(2),
+ BUF_ATTR_QUEUED = BIT(3),
+ BUF_ATTR_DEQUEUED = BIT(4),
+ BUF_ATTR_BUFFER_DONE = BIT(5),
+};
+
+struct iris_buffer {
+ struct list_head list;
+ struct iris_inst *inst;
+ enum iris_buffer_type type;
+ u32 index;
+ int fd;
+ u32 buffer_size;
+ u32 data_offset;
+ u32 data_size;
+ u64 device_addr;
+ void *kvaddr;
+ unsigned long dma_attrs;
+ u32 flags;
+ u64 timestamp;
+ enum iris_buffer_attributes attr;
+ void *dmabuf;
+ struct sg_table *sg_table;
+ struct dma_buf_attachment *attach;
+};
+
#endif
@@ -42,6 +42,30 @@ u32 get_port_info(struct iris_inst *inst,
return HFI_PORT_NONE;
}
+enum iris_buffer_type v4l2_type_to_driver(u32 type)
+{
+ switch (type) {
+ case INPUT_MPLANE:
+ return BUF_INPUT;
+ case OUTPUT_MPLANE:
+ return BUF_OUTPUT;
+ default:
+ return 0;
+ }
+}
+
+int get_mbpf(struct iris_inst *inst)
+{
+ int height = 0, width = 0;
+ struct v4l2_format *inp_f;
+
+ inp_f = inst->fmt_src;
+ width = max(inp_f->fmt.pix_mp.width, inst->crop.width);
+ height = max(inp_f->fmt.pix_mp.height, inst->crop.height);
+
+ return NUM_MBS_PER_FRAME(height, width);
+}
+
static int process_inst_timeout(struct iris_inst *inst)
{
struct iris_inst *instance;
@@ -11,6 +11,7 @@
#include "iris_core.h"
#include "iris_instance.h"
+#include "iris_buffer.h"
#include "platform_common.h"
#define NUM_MBS_PER_FRAME(__height, __width) \
@@ -21,7 +22,8 @@ bool res_is_less_than(u32 width, u32 height,
u32 ref_width, u32 ref_height);
u32 get_port_info(struct iris_inst *inst,
enum plat_inst_cap_type cap_id);
-
+enum iris_buffer_type v4l2_type_to_driver(u32 type);
+int get_mbpf(struct iris_inst *inst);
int close_session(struct iris_inst *inst);
#endif
@@ -8,6 +8,8 @@
#include <media/v4l2-ctrls.h>
+#include "iris_buffer.h"
+#include "iris_common.h"
#include "iris_core.h"
#include "iris_common.h"
#include "platform_common.h"
@@ -25,6 +27,7 @@
* @fmt_src: structure of v4l2_format for source
* @fmt_dst: structure of v4l2_format for destination
* @ctrl_handler: reference of v4l2 ctrl handler
+ * @crop: structure of crop info
* @packet: HFI packet
* @packet_size: HFI packet size
* @completions: structure of signal completions
@@ -32,6 +35,7 @@
* @num_ctrls: supported number of controls
* @caps_list: list head of capability
* @codec: codec type
+ * @buffers: structure of buffer info
*/
struct iris_inst {
@@ -45,6 +49,7 @@ struct iris_inst {
struct v4l2_format *fmt_src;
struct v4l2_format *fmt_dst;
struct v4l2_ctrl_handler ctrl_handler;
+ struct rect_desc crop;
void *packet;
u32 packet_size;
struct completion completions[MAX_SIGNAL];
@@ -52,6 +57,7 @@ struct iris_inst {
u32 num_ctrls;
struct list_head caps_list;
enum codec_type codec;
+ struct iris_buffers_info buffers;
};
#endif
new file mode 100644
@@ -0,0 +1,71 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include "iris_buffer.h"
+#include "iris_core.h"
+#include "iris_helpers.h"
+#include "iris_instance.h"
+#include "iris_vb2.h"
+
+int iris_vb2_queue_setup(struct vb2_queue *q,
+ unsigned int *num_buffers, unsigned int *num_planes,
+ unsigned int sizes[], struct device *alloc_devs[])
+{
+ enum iris_buffer_type buffer_type = 0;
+ struct iris_buffers *buffers;
+ struct iris_inst *inst;
+ struct iris_core *core;
+ struct v4l2_format *f;
+ int ret;
+
+ if (!q || !num_buffers || !num_planes || !sizes)
+ return -EINVAL;
+
+ inst = vb2_get_drv_priv(q);
+ if (!inst || !inst->core)
+ return -EINVAL;
+
+ core = inst->core;
+
+ if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+ f = inst->fmt_src;
+ else
+ f = inst->fmt_dst;
+
+ if (*num_planes) {
+ if (*num_planes != f->fmt.pix_mp.num_planes ||
+ sizes[0] < f->fmt.pix_mp.plane_fmt[0].sizeimage)
+ return -EINVAL;
+ }
+
+ buffer_type = v4l2_type_to_driver(q->type);
+ if (!buffer_type)
+ return -EINVAL;
+
+ ret = iris_free_buffers(inst, buffer_type);
+ if (ret)
+ return ret;
+
+ buffers = iris_get_buffer_list(inst, buffer_type);
+ if (!buffers)
+ return -EINVAL;
+
+ buffers->min_count = iris_get_buf_min_count(inst, buffer_type);
+ if (*num_buffers < buffers->min_count)
+ *num_buffers = buffers->min_count;
+ buffers->actual_count = *num_buffers;
+ *num_planes = 1;
+
+ buffers->size = iris_get_buffer_size(inst, buffer_type);
+
+ f->fmt.pix_mp.plane_fmt[0].sizeimage = buffers->size;
+ sizes[0] = f->fmt.pix_mp.plane_fmt[0].sizeimage;
+
+ ret = iris_allocate_buffers(inst, buffer_type, *num_buffers);
+
+ q->dev = core->dev;
+
+ return ret;
+}
new file mode 100644
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef _IRIS_VB2_H_
+#define _IRIS_VB2_H_
+
+#include <media/videobuf2-v4l2.h>
+
+int iris_vb2_queue_setup(struct vb2_queue *q,
+ unsigned int *num_buffers, unsigned int *num_planes,
+ unsigned int sizes[], struct device *alloc_devs[]);
+
+#endif
@@ -3,6 +3,7 @@
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
+#include "iris_buffer.h"
#include "iris_common.h"
#include "iris_vdec.h"
@@ -22,7 +23,7 @@ void vdec_inst_init(struct iris_inst *inst)
f->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264;
f->fmt.pix_mp.num_planes = 1;
f->fmt.pix_mp.plane_fmt[0].bytesperline = 0;
- f->fmt.pix_mp.plane_fmt[0].sizeimage = DEFAULT_BUF_SIZE;
+ f->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_INPUT);
f->fmt.pix_mp.field = V4L2_FIELD_NONE;
f = inst->fmt_dst;
@@ -32,7 +33,7 @@ void vdec_inst_init(struct iris_inst *inst)
f->fmt.pix_mp.height = ALIGN(DEFAULT_HEIGHT, 32);
f->fmt.pix_mp.num_planes = 1;
f->fmt.pix_mp.plane_fmt[0].bytesperline = ALIGN(DEFAULT_WIDTH, 128);
- f->fmt.pix_mp.plane_fmt[0].sizeimage = DEFAULT_BUF_SIZE;
+ f->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_OUTPUT);
f->fmt.pix_mp.field = V4L2_FIELD_NONE;
f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_DEFAULT;
f->fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_DEFAULT;
@@ -10,6 +10,7 @@
#include "iris_vdec.h"
#include "iris_vidc.h"
#include "iris_ctrls.h"
+#include "iris_vb2.h"
static int vidc_v4l2_fh_init(struct iris_inst *inst)
{
@@ -168,13 +169,22 @@ int vidc_open(struct file *filp)
inst->core = core;
inst->session_id = hash32_ptr(inst);
mutex_init(&inst->ctx_q_lock);
- for (i = 0; i < MAX_SIGNAL; i++)
- init_completion(&inst->completions[i]);
ret = vidc_add_session(inst);
if (ret)
goto fail_free_inst;
+ INIT_LIST_HEAD(&inst->buffers.input.list);
+ INIT_LIST_HEAD(&inst->buffers.output.list);
+ INIT_LIST_HEAD(&inst->buffers.read_only.list);
+ INIT_LIST_HEAD(&inst->buffers.bin.list);
+ INIT_LIST_HEAD(&inst->buffers.arp.list);
+ INIT_LIST_HEAD(&inst->buffers.comv.list);
+ INIT_LIST_HEAD(&inst->buffers.non_comv.list);
+ INIT_LIST_HEAD(&inst->buffers.line.list);
+ INIT_LIST_HEAD(&inst->buffers.dpb.list);
+ INIT_LIST_HEAD(&inst->buffers.persist.list);
+ INIT_LIST_HEAD(&inst->buffers.vpss.list);
INIT_LIST_HEAD(&inst->caps_list);
for (i = 0; i < MAX_SIGNAL; i++)
init_completion(&inst->completions[i]);
@@ -306,9 +316,14 @@ static const struct v4l2_file_operations v4l2_file_ops = {
.poll = vidc_poll,
};
+static const struct vb2_ops iris_vb2_ops = {
+ .queue_setup = iris_vb2_queue_setup,
+};
+
int init_ops(struct iris_core *core)
{
core->v4l2_file_ops = &v4l2_file_ops;
+ core->vb2_ops = &iris_vb2_ops;
return 0;
}
@@ -9,6 +9,8 @@
#include <linux/bits.h>
#include <media/v4l2-ctrls.h>
+#include "iris_common.h"
+
struct iris_core;
struct iris_inst;
@@ -35,20 +37,6 @@ struct iris_inst;
.bank_spreading = bsp, \
}
-enum codec_type {
- H264 = BIT(0),
- HEVC = BIT(1),
- VP9 = BIT(2),
-};
-
-enum colorformat_type {
- FMT_NONE = 0,
- FMT_NV12C = BIT(0),
- FMT_NV12 = BIT(1),
- FMT_NV21 = BIT(2),
- FMT_TP10C = BIT(3),
-};
-
enum stage_type {
STAGE_NONE = 0,
STAGE_1 = 1,
Implement queue_setup vb2_ops. Calculate the buffer count and buffer size as par video hardware requirement and updates to client. Also, allocate the video driver buffers for output and capture plane. Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com> --- drivers/media/platform/qcom/vcodec/iris/Makefile | 4 +- .../media/platform/qcom/vcodec/iris/iris_buffer.c | 179 +++++++++++++++++++++ .../media/platform/qcom/vcodec/iris/iris_buffer.h | 49 ++++++ .../media/platform/qcom/vcodec/iris/iris_common.h | 71 +++++++- .../media/platform/qcom/vcodec/iris/iris_helpers.c | 24 +++ .../media/platform/qcom/vcodec/iris/iris_helpers.h | 4 +- .../platform/qcom/vcodec/iris/iris_instance.h | 6 + drivers/media/platform/qcom/vcodec/iris/iris_vb2.c | 71 ++++++++ drivers/media/platform/qcom/vcodec/iris/iris_vb2.h | 15 ++ .../media/platform/qcom/vcodec/iris/iris_vdec.c | 5 +- .../media/platform/qcom/vcodec/iris/iris_vidc.c | 19 ++- .../platform/qcom/vcodec/iris/platform_common.h | 16 +- 12 files changed, 442 insertions(+), 21 deletions(-) create mode 100644 drivers/media/platform/qcom/vcodec/iris/iris_buffer.c create mode 100644 drivers/media/platform/qcom/vcodec/iris/iris_buffer.h create mode 100644 drivers/media/platform/qcom/vcodec/iris/iris_vb2.c create mode 100644 drivers/media/platform/qcom/vcodec/iris/iris_vb2.h