Commit 38fc8bea authored by Dikshita Agarwal's avatar Dikshita Agarwal Committed by Hans Verkuil
Browse files

media: iris: implement reqbuf ioctl with vb2_queue_setup



Implement the reqbuf IOCTL op and the vb2_queue_setup vb2 op in the
driver with necessary hooks.

Reviewed-by: default avatarHans Verkuil <hverkuil@xs4all.nl>
Tested-by: Stefan Schmidt <stefan.schmidt@linaro.org> # x1e80100 (Dell XPS 13 9345)
Reviewed-by: default avatarStefan Schmidt <stefan.schmidt@linaro.org>
Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-HDK
Signed-off-by: default avatarDikshita Agarwal <quic_dikshita@quicinc.com>
Signed-off-by: default avatarHans Verkuil <hverkuil@xs4all.nl>
parent bb8a95aa
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
iris-objs += iris_core.o \
iris-objs += iris_buffer.o \
             iris_core.o \
             iris_firmware.o \
             iris_hfi_common.o \
             iris_hfi_gen1_command.o \
@@ -10,9 +11,13 @@ iris-objs += iris_core.o \
             iris_platform_sm8550.o \
             iris_probe.o \
             iris_resources.o \
             iris_utils.o \
             iris_vidc.o \
             iris_vb2.o \
             iris_vdec.o \
             iris_vpu2.o \
             iris_vpu3.o \
             iris_vpu_buffer.o \
             iris_vpu_common.o \

obj-$(CONFIG_VIDEO_QCOM_IRIS) += iris.o
+119 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
 */

#include <media/v4l2-mem2mem.h>

#include "iris_buffer.h"
#include "iris_instance.h"

#define PIXELS_4K 4096
#define MAX_WIDTH 4096
#define MAX_HEIGHT 2304
#define Y_STRIDE_ALIGN 128
#define UV_STRIDE_ALIGN 128
#define Y_SCANLINE_ALIGN 32
#define UV_SCANLINE_ALIGN 16
#define UV_SCANLINE_ALIGN_QC08C 32
#define META_STRIDE_ALIGNED 64
#define META_SCANLINE_ALIGNED 16
#define NUM_MBS_4K (DIV_ROUND_UP(MAX_WIDTH, 16) * DIV_ROUND_UP(MAX_HEIGHT, 16))

/*
 * NV12:
 * YUV 4:2:0 image with a plane of 8 bit Y samples followed
 * by an interleaved U/V plane containing 8 bit 2x2 subsampled
 * colour difference samples.
 *
 * <-Y/UV_Stride (aligned to 128)->
 * <------- Width ------->
 * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  ^           ^
 * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  |           |
 * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  Height      |
 * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  |          y_scanlines (aligned to 32)
 * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  |           |
 * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  |           |
 * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  |           |
 * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  V           |
 * . . . . . . . . . . . . . . . .              |
 * . . . . . . . . . . . . . . . .              |
 * . . . . . . . . . . . . . . . .              |
 * . . . . . . . . . . . . . . . .              V
 * U V U V U V U V U V U V . . . .  ^
 * U V U V U V U V U V U V . . . .  |
 * U V U V U V U V U V U V . . . .  |
 * U V U V U V U V U V U V . . . .  uv_scanlines (aligned to 16)
 * . . . . . . . . . . . . . . . .  |
 * . . . . . . . . . . . . . . . .  V
 * . . . . . . . . . . . . . . . .  --> Buffer size aligned to 4K
 *
 * y_stride : Width aligned to 128
 * uv_stride : Width aligned to 128
 * y_scanlines: Height aligned to 32
 * uv_scanlines: Height/2 aligned to 16
 * Total size = align((y_stride * y_scanlines
 *          + uv_stride * uv_scanlines , 4096)
 *
 * Note: All the alignments are hardware requirements.
 */
static u32 iris_yuv_buffer_size_nv12(struct iris_inst *inst)
{
	u32 y_plane, uv_plane, y_stride, uv_stride, y_scanlines, uv_scanlines;
	struct v4l2_format *f = inst->fmt_dst;

	y_stride = ALIGN(f->fmt.pix_mp.width, Y_STRIDE_ALIGN);
	uv_stride = ALIGN(f->fmt.pix_mp.width, UV_STRIDE_ALIGN);
	y_scanlines = ALIGN(f->fmt.pix_mp.height, Y_SCANLINE_ALIGN);
	uv_scanlines = ALIGN((f->fmt.pix_mp.height + 1) >> 1, UV_SCANLINE_ALIGN);
	y_plane = y_stride * y_scanlines;
	uv_plane = uv_stride * uv_scanlines;

	return ALIGN(y_plane + uv_plane, PIXELS_4K);
}

static u32 iris_bitstream_buffer_size(struct iris_inst *inst)
{
	struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps;
	u32 base_res_mbs = NUM_MBS_4K;
	u32 frame_size, num_mbs;
	u32 div_factor = 2;

	num_mbs = iris_get_mbpf(inst);
	if (num_mbs > NUM_MBS_4K) {
		div_factor = 4;
		base_res_mbs = caps->max_mbpf;
	}

	/*
	 * frame_size = YUVsize / div_factor
	 * where YUVsize = resolution_in_MBs * MBs_in_pixel * 3 / 2
	 */
	frame_size = base_res_mbs * (16 * 16) * 3 / 2 / div_factor;

	return ALIGN(frame_size, PIXELS_4K);
}

int iris_get_buffer_size(struct iris_inst *inst,
			 enum iris_buffer_type buffer_type)
{
	switch (buffer_type) {
	case BUF_INPUT:
		return iris_bitstream_buffer_size(inst);
	case BUF_OUTPUT:
		return iris_yuv_buffer_size_nv12(inst);
	default:
		return 0;
	}
}

void iris_vb2_queue_error(struct iris_inst *inst)
{
	struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;
	struct vb2_queue *q;

	q = v4l2_m2m_get_src_vq(m2m_ctx);
	vb2_queue_error(q);
	q = v4l2_m2m_get_dst_vq(m2m_ctx);
	vb2_queue_error(q);
}
+107 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
 */

#ifndef __IRIS_BUFFER_H__
#define __IRIS_BUFFER_H__

#include <media/videobuf2-v4l2.h>

struct iris_inst;

#define to_iris_buffer(ptr)	container_of(ptr, struct iris_buffer, vb2)

/**
 * enum iris_buffer_type
 *
 * @BUF_INPUT: input buffer to the iris hardware
 * @BUF_OUTPUT: output buffer from the iris hardware
 * @BUF_BIN: buffer to store intermediate bin data
 * @BUF_ARP: buffer for auto register programming
 * @BUF_COMV: buffer to store colocated motion vectors
 * @BUF_NON_COMV: buffer to hold config data for HW
 * @BUF_LINE: buffer to store decoding/encoding context data for HW
 * @BUF_DPB: buffer to store display picture buffers for reference
 * @BUF_PERSIST: buffer to store session context data
 * @BUF_SCRATCH_1: buffer to store decoding/encoding context data for HW
 * @BUF_TYPE_MAX: max buffer types
 */
enum iris_buffer_type {
	BUF_INPUT = 1,
	BUF_OUTPUT,
	BUF_BIN,
	BUF_ARP,
	BUF_COMV,
	BUF_NON_COMV,
	BUF_LINE,
	BUF_DPB,
	BUF_PERSIST,
	BUF_SCRATCH_1,
	BUF_TYPE_MAX,
};

/*
 * enum iris_buffer_attributes
 *
 * BUF_ATTR_DEFERRED: buffer queued by client but not submitted to firmware.
 * BUF_ATTR_PENDING_RELEASE: buffers requested to be released from firmware.
 * BUF_ATTR_QUEUED: buffers submitted to firmware.
 * BUF_ATTR_DEQUEUED: buffers received from firmware.
 * BUF_ATTR_BUFFER_DONE: buffers sent back to vb2.
 */
enum iris_buffer_attributes {
	BUF_ATTR_DEFERRED		= BIT(0),
	BUF_ATTR_PENDING_RELEASE	= BIT(1),
	BUF_ATTR_QUEUED			= BIT(2),
	BUF_ATTR_DEQUEUED		= BIT(3),
	BUF_ATTR_BUFFER_DONE		= BIT(4),
};

/**
 * struct iris_buffer
 *
 * @vb2: v4l2 vb2 buffer
 * @list: list head for the iris_buffers structure
 * @inst: iris instance structure
 * @type: enum for type of iris buffer
 * @index: identifier for the iris buffer
 * @fd: file descriptor of the buffer
 * @buffer_size: accessible buffer size in bytes starting from addr_offset
 * @data_offset: accessible buffer offset from base address
 * @data_size: data size in bytes
 * @device_addr: device address of the buffer
 * @kvaddr: kernel virtual address of the buffer
 * @dma_attrs: dma attributes
 * @flags: buffer flags. It is represented as bit masks.
 * @timestamp: timestamp of the buffer in nano seconds (ns)
 * @attr: enum for iris buffer attributes
 */
struct iris_buffer {
	struct vb2_v4l2_buffer		vb2;
	struct list_head		list;
	struct iris_inst		*inst;
	enum iris_buffer_type		type;
	u32				index;
	int				fd;
	size_t				buffer_size;
	u32				data_offset;
	size_t				data_size;
	dma_addr_t			device_addr;
	void				*kvaddr;
	unsigned long			dma_attrs;
	u32				flags; /* V4L2_BUF_FLAG_* */
	u64				timestamp;
	enum iris_buffer_attributes	attr;
};

struct iris_buffers {
	struct list_head	list;
	u32			min_count;
	u32			size;
};

int iris_get_buffer_size(struct iris_inst *inst, enum iris_buffer_type buffer_type);
void iris_vb2_queue_error(struct iris_inst *inst);

#endif
+6 −0
Original line number Diff line number Diff line
@@ -34,6 +34,8 @@ struct icc_info {
 * @v4l2_dev: a holder for v4l2 device structure
 * @vdev_dec: iris video device structure for decoder
 * @iris_v4l2_file_ops: iris v4l2 file ops
 * @iris_v4l2_ioctl_ops: iris v4l2 ioctl ops
 * @iris_vb2_ops: iris vb2 ops
 * @icc_tbl: table of iris interconnects
 * @icc_count: count of iris interconnects
 * @pmdomain_tbl: table of iris power domains
@@ -60,6 +62,7 @@ struct icc_info {
 * @core_init_done: structure of signal completion for system response
 * @intr_status: interrupt status
 * @sys_error_handler: a delayed work for handling system fatal error
 * @instances: a list_head of all instances
 */

struct iris_core {
@@ -69,6 +72,8 @@ struct iris_core {
	struct v4l2_device			v4l2_dev;
	struct video_device			*vdev_dec;
	const struct v4l2_file_operations	*iris_v4l2_file_ops;
	const struct v4l2_ioctl_ops		*iris_v4l2_ioctl_ops;
	const struct vb2_ops			*iris_vb2_ops;
	struct icc_bulk_data			*icc_tbl;
	u32					icc_count;
	struct dev_pm_domain_list		*pmdomain_tbl;
@@ -95,6 +100,7 @@ struct iris_core {
	struct completion			core_init_done;
	u32					intr_status;
	struct delayed_work			sys_error_handler;
	struct list_head			instances;
};

int iris_core_init(struct iris_core *core);
+3 −0
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@
#include <linux/types.h>
#include <media/v4l2-device.h>

struct iris_inst;
struct iris_core;

enum hfi_packet_port_type {
@@ -47,6 +48,8 @@ struct iris_hfi_command_ops {
	int (*sys_image_version)(struct iris_core *core);
	int (*sys_interframe_powercollapse)(struct iris_core *core);
	int (*sys_pc_prep)(struct iris_core *core);
	int (*session_open)(struct iris_inst *inst);
	int (*session_close)(struct iris_inst *inst);
};

struct iris_hfi_response_ops {
Loading