Commit b530b95d authored by Vedang Nagar's avatar Vedang Nagar Committed by Hans Verkuil
Browse files

media: iris: implement s_fmt, g_fmt and try_fmt ioctls



Implement the s_fmt, g_fmt and try_fmt ioctl ops with the necessary
hooks.

Signed-off-by: default avatarVedang Nagar <quic_vnagar@quicinc.com>
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 38fc8bea
Loading
Loading
Loading
Loading
+122 −0
Original line number Diff line number Diff line
@@ -3,6 +3,8 @@
 * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
 */

#include <media/v4l2-mem2mem.h>

#include "iris_buffer.h"
#include "iris_instance.h"
#include "iris_vdec.h"
@@ -10,6 +12,7 @@

#define DEFAULT_WIDTH 320
#define DEFAULT_HEIGHT 240
#define DEFAULT_CODEC_ALIGNMENT 16

void iris_vdec_inst_init(struct iris_inst *inst)
{
@@ -54,3 +57,122 @@ void iris_vdec_inst_deinit(struct iris_inst *inst)
	kfree(inst->fmt_dst);
	kfree(inst->fmt_src);
}

int iris_vdec_try_fmt(struct iris_inst *inst, struct v4l2_format *f)
{
	struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
	struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;
	struct v4l2_format *f_inst;
	struct vb2_queue *src_q;

	memset(pixmp->reserved, 0, sizeof(pixmp->reserved));
	switch (f->type) {
	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
		if (f->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_H264) {
			f_inst = inst->fmt_src;
			f->fmt.pix_mp.width = f_inst->fmt.pix_mp.width;
			f->fmt.pix_mp.height = f_inst->fmt.pix_mp.height;
			f->fmt.pix_mp.pixelformat = f_inst->fmt.pix_mp.pixelformat;
		}
		break;
	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
		if (f->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_NV12) {
			f_inst = inst->fmt_dst;
			f->fmt.pix_mp.pixelformat = f_inst->fmt.pix_mp.pixelformat;
			f->fmt.pix_mp.width = f_inst->fmt.pix_mp.width;
			f->fmt.pix_mp.height = f_inst->fmt.pix_mp.height;
		}

		src_q = v4l2_m2m_get_src_vq(m2m_ctx);
		if (vb2_is_streaming(src_q)) {
			f_inst = inst->fmt_src;
			f->fmt.pix_mp.height = f_inst->fmt.pix_mp.height;
			f->fmt.pix_mp.width = f_inst->fmt.pix_mp.width;
		}
		break;
	default:
		return -EINVAL;
	}

	if (pixmp->field == V4L2_FIELD_ANY)
		pixmp->field = V4L2_FIELD_NONE;

	pixmp->num_planes = 1;

	return 0;
}

int iris_vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f)
{
	struct v4l2_format *fmt, *output_fmt;
	struct vb2_queue *q;
	u32 codec_align;

	q = v4l2_m2m_get_vq(inst->m2m_ctx, f->type);
	if (!q)
		return -EINVAL;

	if (vb2_is_busy(q))
		return -EBUSY;

	iris_vdec_try_fmt(inst, f);

	switch (f->type) {
	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
		if (f->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_H264)
			return -EINVAL;

		fmt = inst->fmt_src;
		fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;

		codec_align = DEFAULT_CODEC_ALIGNMENT;
		fmt->fmt.pix_mp.width = ALIGN(f->fmt.pix_mp.width, codec_align);
		fmt->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height, codec_align);
		fmt->fmt.pix_mp.num_planes = 1;
		fmt->fmt.pix_mp.plane_fmt[0].bytesperline = 0;
		fmt->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_INPUT);
		inst->buffers[BUF_INPUT].min_count = iris_vpu_buf_count(inst, BUF_INPUT);
		inst->buffers[BUF_INPUT].size = fmt->fmt.pix_mp.plane_fmt[0].sizeimage;

		fmt->fmt.pix_mp.colorspace = f->fmt.pix_mp.colorspace;
		fmt->fmt.pix_mp.xfer_func = f->fmt.pix_mp.xfer_func;
		fmt->fmt.pix_mp.ycbcr_enc = f->fmt.pix_mp.ycbcr_enc;
		fmt->fmt.pix_mp.quantization = f->fmt.pix_mp.quantization;

		output_fmt = inst->fmt_dst;
		output_fmt->fmt.pix_mp.colorspace = f->fmt.pix_mp.colorspace;
		output_fmt->fmt.pix_mp.xfer_func = f->fmt.pix_mp.xfer_func;
		output_fmt->fmt.pix_mp.ycbcr_enc = f->fmt.pix_mp.ycbcr_enc;
		output_fmt->fmt.pix_mp.quantization = f->fmt.pix_mp.quantization;

		inst->crop.left = 0;
		inst->crop.top = 0;
		inst->crop.width = f->fmt.pix_mp.width;
		inst->crop.height = f->fmt.pix_mp.height;
		break;
	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
		fmt = inst->fmt_dst;
		fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
		if (fmt->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_NV12)
			return -EINVAL;
		fmt->fmt.pix_mp.pixelformat = f->fmt.pix_mp.pixelformat;
		fmt->fmt.pix_mp.width = ALIGN(f->fmt.pix_mp.width, 128);
		fmt->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height, 32);
		fmt->fmt.pix_mp.num_planes = 1;
		fmt->fmt.pix_mp.plane_fmt[0].bytesperline = ALIGN(f->fmt.pix_mp.width, 128);
		fmt->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_OUTPUT);
		inst->buffers[BUF_OUTPUT].min_count = iris_vpu_buf_count(inst, BUF_OUTPUT);
		inst->buffers[BUF_OUTPUT].size = fmt->fmt.pix_mp.plane_fmt[0].sizeimage;

		inst->crop.top = 0;
		inst->crop.left = 0;
		inst->crop.width = f->fmt.pix_mp.width;
		inst->crop.height = f->fmt.pix_mp.height;
		break;
	default:
		return -EINVAL;
	}
	memcpy(f, fmt, sizeof(*fmt));

	return 0;
}
+2 −0
Original line number Diff line number Diff line
@@ -10,5 +10,7 @@ struct iris_inst;

void iris_vdec_inst_init(struct iris_inst *inst);
void iris_vdec_inst_deinit(struct iris_inst *inst);
int iris_vdec_try_fmt(struct iris_inst *inst, struct v4l2_format *f);
int iris_vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f);

#endif
+48 −0
Original line number Diff line number Diff line
@@ -217,6 +217,48 @@ int iris_close(struct file *filp)
	return 0;
}

static int iris_try_fmt_vid_mplane(struct file *filp, void *fh, struct v4l2_format *f)
{
	struct iris_inst *inst = iris_get_inst(filp, NULL);
	int ret;

	mutex_lock(&inst->lock);
	ret = iris_vdec_try_fmt(inst, f);
	mutex_unlock(&inst->lock);

	return ret;
}

static int iris_s_fmt_vid_mplane(struct file *filp, void *fh, struct v4l2_format *f)
{
	struct iris_inst *inst = iris_get_inst(filp, NULL);
	int ret;

	mutex_lock(&inst->lock);
	ret = iris_vdec_s_fmt(inst, f);
	mutex_unlock(&inst->lock);

	return ret;
}

static int iris_g_fmt_vid_mplane(struct file *filp, void *fh, struct v4l2_format *f)
{
	struct iris_inst *inst = iris_get_inst(filp, NULL);
	int ret = 0;

	mutex_lock(&inst->lock);
	if (V4L2_TYPE_IS_OUTPUT(f->type))
		*f = *inst->fmt_src;
	else if (V4L2_TYPE_IS_CAPTURE(f->type))
		*f = *inst->fmt_dst;
	else
		ret = -EINVAL;

	mutex_unlock(&inst->lock);

	return ret;
}

static struct v4l2_file_operations iris_v4l2_file_ops = {
	.owner                          = THIS_MODULE,
	.open                           = iris_open,
@@ -231,6 +273,12 @@ static const struct vb2_ops iris_vb2_ops = {
};

static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops = {
	.vidioc_try_fmt_vid_cap_mplane  = iris_try_fmt_vid_mplane,
	.vidioc_try_fmt_vid_out_mplane  = iris_try_fmt_vid_mplane,
	.vidioc_s_fmt_vid_cap_mplane    = iris_s_fmt_vid_mplane,
	.vidioc_s_fmt_vid_out_mplane    = iris_s_fmt_vid_mplane,
	.vidioc_g_fmt_vid_cap_mplane    = iris_g_fmt_vid_mplane,
	.vidioc_g_fmt_vid_out_mplane    = iris_g_fmt_vid_mplane,
	.vidioc_reqbufs                 = v4l2_m2m_ioctl_reqbufs,
};