162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *	Video for Linux Two
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci *	A generic video device interface for the LINUX operating system
662306a36Sopenharmony_ci *	using a set of device structures/vectors for low level operations.
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci *	This file replaces the videodev.c file that comes with the
962306a36Sopenharmony_ci *	regular kernel distribution.
1062306a36Sopenharmony_ci *
1162306a36Sopenharmony_ci * Author:	Bill Dirks <bill@thedirks.org>
1262306a36Sopenharmony_ci *		based on code by Alan Cox, <alan@cymru.net>
1362306a36Sopenharmony_ci */
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci/*
1662306a36Sopenharmony_ci * Video capture interface for Linux
1762306a36Sopenharmony_ci *
1862306a36Sopenharmony_ci *	A generic video device interface for the LINUX operating system
1962306a36Sopenharmony_ci *	using a set of device structures/vectors for low level operations.
2062306a36Sopenharmony_ci *
2162306a36Sopenharmony_ci * Author:	Alan Cox, <alan@lxorguk.ukuu.org.uk>
2262306a36Sopenharmony_ci *
2362306a36Sopenharmony_ci * Fixes:
2462306a36Sopenharmony_ci */
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci/*
2762306a36Sopenharmony_ci * Video4linux 1/2 integration by Justin Schoeman
2862306a36Sopenharmony_ci * <justin@suntiger.ee.up.ac.za>
2962306a36Sopenharmony_ci * 2.4 PROCFS support ported from 2.4 kernels by
3062306a36Sopenharmony_ci *  Iñaki García Etxebarria <garetxe@euskalnet.net>
3162306a36Sopenharmony_ci * Makefile fix by "W. Michael Petullo" <mike@flyn.org>
3262306a36Sopenharmony_ci * 2.4 devfs support ported from 2.4 kernels by
3362306a36Sopenharmony_ci *  Dan Merillat <dan@merillat.org>
3462306a36Sopenharmony_ci * Added Gerd Knorrs v4l1 enhancements (Justin Schoeman)
3562306a36Sopenharmony_ci */
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci#include <linux/module.h>
3862306a36Sopenharmony_ci#include <linux/types.h>
3962306a36Sopenharmony_ci#include <linux/kernel.h>
4062306a36Sopenharmony_ci#include <linux/mm.h>
4162306a36Sopenharmony_ci#include <linux/string.h>
4262306a36Sopenharmony_ci#include <linux/errno.h>
4362306a36Sopenharmony_ci#include <linux/uaccess.h>
4462306a36Sopenharmony_ci#include <asm/io.h>
4562306a36Sopenharmony_ci#include <asm/div64.h>
4662306a36Sopenharmony_ci#include <media/v4l2-common.h>
4762306a36Sopenharmony_ci#include <media/v4l2-device.h>
4862306a36Sopenharmony_ci#include <media/v4l2-ctrls.h>
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci#include <linux/videodev2.h>
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci/*
5362306a36Sopenharmony_ci *
5462306a36Sopenharmony_ci *	V 4 L 2   D R I V E R   H E L P E R   A P I
5562306a36Sopenharmony_ci *
5662306a36Sopenharmony_ci */
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci/*
5962306a36Sopenharmony_ci *  Video Standard Operations (contributed by Michael Schimek)
6062306a36Sopenharmony_ci */
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci/* Helper functions for control handling			     */
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci/* Fill in a struct v4l2_queryctrl */
6562306a36Sopenharmony_ciint v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 _min, s32 _max, s32 _step, s32 _def)
6662306a36Sopenharmony_ci{
6762306a36Sopenharmony_ci	const char *name;
6862306a36Sopenharmony_ci	s64 min = _min;
6962306a36Sopenharmony_ci	s64 max = _max;
7062306a36Sopenharmony_ci	u64 step = _step;
7162306a36Sopenharmony_ci	s64 def = _def;
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci	v4l2_ctrl_fill(qctrl->id, &name, &qctrl->type,
7462306a36Sopenharmony_ci		       &min, &max, &step, &def, &qctrl->flags);
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci	if (name == NULL)
7762306a36Sopenharmony_ci		return -EINVAL;
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci	qctrl->minimum = min;
8062306a36Sopenharmony_ci	qctrl->maximum = max;
8162306a36Sopenharmony_ci	qctrl->step = step;
8262306a36Sopenharmony_ci	qctrl->default_value = def;
8362306a36Sopenharmony_ci	qctrl->reserved[0] = qctrl->reserved[1] = 0;
8462306a36Sopenharmony_ci	strscpy(qctrl->name, name, sizeof(qctrl->name));
8562306a36Sopenharmony_ci	return 0;
8662306a36Sopenharmony_ci}
8762306a36Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_query_fill);
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci/* Clamp x to be between min and max, aligned to a multiple of 2^align.  min
9062306a36Sopenharmony_ci * and max don't have to be aligned, but there must be at least one valid
9162306a36Sopenharmony_ci * value.  E.g., min=17,max=31,align=4 is not allowed as there are no multiples
9262306a36Sopenharmony_ci * of 16 between 17 and 31.  */
9362306a36Sopenharmony_cistatic unsigned int clamp_align(unsigned int x, unsigned int min,
9462306a36Sopenharmony_ci				unsigned int max, unsigned int align)
9562306a36Sopenharmony_ci{
9662306a36Sopenharmony_ci	/* Bits that must be zero to be aligned */
9762306a36Sopenharmony_ci	unsigned int mask = ~((1 << align) - 1);
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	/* Clamp to aligned min and max */
10062306a36Sopenharmony_ci	x = clamp(x, (min + ~mask) & mask, max & mask);
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci	/* Round to nearest aligned value */
10362306a36Sopenharmony_ci	if (align)
10462306a36Sopenharmony_ci		x = (x + (1 << (align - 1))) & mask;
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	return x;
10762306a36Sopenharmony_ci}
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_cistatic unsigned int clamp_roundup(unsigned int x, unsigned int min,
11062306a36Sopenharmony_ci				   unsigned int max, unsigned int alignment)
11162306a36Sopenharmony_ci{
11262306a36Sopenharmony_ci	x = clamp(x, min, max);
11362306a36Sopenharmony_ci	if (alignment)
11462306a36Sopenharmony_ci		x = round_up(x, alignment);
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci	return x;
11762306a36Sopenharmony_ci}
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_civoid v4l_bound_align_image(u32 *w, unsigned int wmin, unsigned int wmax,
12062306a36Sopenharmony_ci			   unsigned int walign,
12162306a36Sopenharmony_ci			   u32 *h, unsigned int hmin, unsigned int hmax,
12262306a36Sopenharmony_ci			   unsigned int halign, unsigned int salign)
12362306a36Sopenharmony_ci{
12462306a36Sopenharmony_ci	*w = clamp_align(*w, wmin, wmax, walign);
12562306a36Sopenharmony_ci	*h = clamp_align(*h, hmin, hmax, halign);
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	/* Usually we don't need to align the size and are done now. */
12862306a36Sopenharmony_ci	if (!salign)
12962306a36Sopenharmony_ci		return;
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci	/* How much alignment do we have? */
13262306a36Sopenharmony_ci	walign = __ffs(*w);
13362306a36Sopenharmony_ci	halign = __ffs(*h);
13462306a36Sopenharmony_ci	/* Enough to satisfy the image alignment? */
13562306a36Sopenharmony_ci	if (walign + halign < salign) {
13662306a36Sopenharmony_ci		/* Max walign where there is still a valid width */
13762306a36Sopenharmony_ci		unsigned int wmaxa = __fls(wmax ^ (wmin - 1));
13862306a36Sopenharmony_ci		/* Max halign where there is still a valid height */
13962306a36Sopenharmony_ci		unsigned int hmaxa = __fls(hmax ^ (hmin - 1));
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci		/* up the smaller alignment until we have enough */
14262306a36Sopenharmony_ci		do {
14362306a36Sopenharmony_ci			if (halign >= hmaxa ||
14462306a36Sopenharmony_ci			    (walign <= halign && walign < wmaxa)) {
14562306a36Sopenharmony_ci				*w = clamp_align(*w, wmin, wmax, walign + 1);
14662306a36Sopenharmony_ci				walign = __ffs(*w);
14762306a36Sopenharmony_ci			} else {
14862306a36Sopenharmony_ci				*h = clamp_align(*h, hmin, hmax, halign + 1);
14962306a36Sopenharmony_ci				halign = __ffs(*h);
15062306a36Sopenharmony_ci			}
15162306a36Sopenharmony_ci		} while (halign + walign < salign);
15262306a36Sopenharmony_ci	}
15362306a36Sopenharmony_ci}
15462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(v4l_bound_align_image);
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ciconst void *
15762306a36Sopenharmony_ci__v4l2_find_nearest_size(const void *array, size_t array_size,
15862306a36Sopenharmony_ci			 size_t entry_size, size_t width_offset,
15962306a36Sopenharmony_ci			 size_t height_offset, s32 width, s32 height)
16062306a36Sopenharmony_ci{
16162306a36Sopenharmony_ci	u32 error, min_error = U32_MAX;
16262306a36Sopenharmony_ci	const void *best = NULL;
16362306a36Sopenharmony_ci	unsigned int i;
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci	if (!array)
16662306a36Sopenharmony_ci		return NULL;
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci	for (i = 0; i < array_size; i++, array += entry_size) {
16962306a36Sopenharmony_ci		const u32 *entry_width = array + width_offset;
17062306a36Sopenharmony_ci		const u32 *entry_height = array + height_offset;
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci		error = abs(*entry_width - width) + abs(*entry_height - height);
17362306a36Sopenharmony_ci		if (error > min_error)
17462306a36Sopenharmony_ci			continue;
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci		min_error = error;
17762306a36Sopenharmony_ci		best = array;
17862306a36Sopenharmony_ci		if (!error)
17962306a36Sopenharmony_ci			break;
18062306a36Sopenharmony_ci	}
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci	return best;
18362306a36Sopenharmony_ci}
18462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(__v4l2_find_nearest_size);
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ciint v4l2_g_parm_cap(struct video_device *vdev,
18762306a36Sopenharmony_ci		    struct v4l2_subdev *sd, struct v4l2_streamparm *a)
18862306a36Sopenharmony_ci{
18962306a36Sopenharmony_ci	struct v4l2_subdev_frame_interval ival = { 0 };
19062306a36Sopenharmony_ci	int ret;
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
19362306a36Sopenharmony_ci	    a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
19462306a36Sopenharmony_ci		return -EINVAL;
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci	if (vdev->device_caps & V4L2_CAP_READWRITE)
19762306a36Sopenharmony_ci		a->parm.capture.readbuffers = 2;
19862306a36Sopenharmony_ci	if (v4l2_subdev_has_op(sd, video, g_frame_interval))
19962306a36Sopenharmony_ci		a->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
20062306a36Sopenharmony_ci	ret = v4l2_subdev_call(sd, video, g_frame_interval, &ival);
20162306a36Sopenharmony_ci	if (!ret)
20262306a36Sopenharmony_ci		a->parm.capture.timeperframe = ival.interval;
20362306a36Sopenharmony_ci	return ret;
20462306a36Sopenharmony_ci}
20562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(v4l2_g_parm_cap);
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ciint v4l2_s_parm_cap(struct video_device *vdev,
20862306a36Sopenharmony_ci		    struct v4l2_subdev *sd, struct v4l2_streamparm *a)
20962306a36Sopenharmony_ci{
21062306a36Sopenharmony_ci	struct v4l2_subdev_frame_interval ival = {
21162306a36Sopenharmony_ci		.interval = a->parm.capture.timeperframe
21262306a36Sopenharmony_ci	};
21362306a36Sopenharmony_ci	int ret;
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
21662306a36Sopenharmony_ci	    a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
21762306a36Sopenharmony_ci		return -EINVAL;
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci	memset(&a->parm, 0, sizeof(a->parm));
22062306a36Sopenharmony_ci	if (vdev->device_caps & V4L2_CAP_READWRITE)
22162306a36Sopenharmony_ci		a->parm.capture.readbuffers = 2;
22262306a36Sopenharmony_ci	else
22362306a36Sopenharmony_ci		a->parm.capture.readbuffers = 0;
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci	if (v4l2_subdev_has_op(sd, video, g_frame_interval))
22662306a36Sopenharmony_ci		a->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
22762306a36Sopenharmony_ci	ret = v4l2_subdev_call(sd, video, s_frame_interval, &ival);
22862306a36Sopenharmony_ci	if (!ret)
22962306a36Sopenharmony_ci		a->parm.capture.timeperframe = ival.interval;
23062306a36Sopenharmony_ci	return ret;
23162306a36Sopenharmony_ci}
23262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(v4l2_s_parm_cap);
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ciconst struct v4l2_format_info *v4l2_format_info(u32 format)
23562306a36Sopenharmony_ci{
23662306a36Sopenharmony_ci	static const struct v4l2_format_info formats[] = {
23762306a36Sopenharmony_ci		/* RGB formats */
23862306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_BGR24,   .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
23962306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_RGB24,   .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
24062306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_HSV24,   .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
24162306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_BGR32,   .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
24262306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_XBGR32,  .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
24362306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_BGRX32,  .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
24462306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_RGB32,   .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
24562306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_XRGB32,  .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
24662306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_RGBX32,  .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
24762306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_HSV32,   .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
24862306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_ARGB32,  .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
24962306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_RGBA32,  .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
25062306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_ABGR32,  .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
25162306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_BGRA32,  .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
25262306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_RGB565,  .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
25362306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_RGB555,  .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
25462306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_BGR666,  .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
25562306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_BGR48_12, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 6, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
25662306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_ABGR64_12, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 8, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci		/* YUV packed formats */
25962306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_YUYV,    .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 },
26062306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_YVYU,    .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 },
26162306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_UYVY,    .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 },
26262306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_VYUY,    .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 },
26362306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_Y212,    .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 },
26462306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_YUV48_12, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 6, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
26562306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_MT2110T, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 5, 10, 0, 0 }, .bpp_div = { 4, 4, 1, 1 }, .hdiv = 2, .vdiv = 2,
26662306a36Sopenharmony_ci		  .block_w = { 16, 8, 0, 0 }, .block_h = { 32, 16, 0, 0 }},
26762306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_MT2110R, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 5, 10, 0, 0 }, .bpp_div = { 4, 4, 1, 1 }, .hdiv = 2, .vdiv = 2,
26862306a36Sopenharmony_ci		  .block_w = { 16, 8, 0, 0 }, .block_h = { 32, 16, 0, 0 }},
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci		/* YUV planar formats */
27162306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_NV12,    .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
27262306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_NV21,    .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
27362306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_NV16,    .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 },
27462306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_NV61,    .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 },
27562306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_NV24,    .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
27662306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_NV42,    .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
27762306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_P010,    .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 2, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 },
27862306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_P012,    .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 2, 4, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_YUV410,  .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 4, .vdiv = 4 },
28162306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_YVU410,  .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 4, .vdiv = 4 },
28262306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_YUV411P, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 4, .vdiv = 1 },
28362306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_YUV420,  .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
28462306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_YVU420,  .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
28562306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_YUV422P, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 },
28662306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_GREY,    .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci		/* Tiled YUV formats */
28962306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_NV12_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
29062306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_NV15_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 5, 10, 0, 0 }, .bpp_div = { 4, 4, 1, 1 }, .hdiv = 2, .vdiv = 2,
29162306a36Sopenharmony_ci		  .block_w = { 4, 2, 0, 0 }, .block_h = { 1, 1, 0, 0 }},
29262306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_P010_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 2, 4, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci		/* YUV planar formats, non contiguous variant */
29562306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_YUV420M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
29662306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_YVU420M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
29762306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_YUV422M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 },
29862306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_YVU422M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 },
29962306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_YUV444M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
30062306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_YVU444M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_NV12M,   .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
30362306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_NV21M,   .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
30462306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_NV16M,   .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 },
30562306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_NV61M,   .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 },
30662306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_P012M,   .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 2, 4, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci		/* Bayer RGB formats */
30962306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_SBGGR8,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
31062306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_SGBRG8,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
31162306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_SGRBG8,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
31262306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_SRGGB8,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
31362306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_SBGGR10,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
31462306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_SGBRG10,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
31562306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_SGRBG10,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
31662306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_SRGGB10,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
31762306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_SBGGR10ALAW8,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
31862306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_SGBRG10ALAW8,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
31962306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_SGRBG10ALAW8,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
32062306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_SRGGB10ALAW8,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
32162306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_SBGGR10DPCM8,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
32262306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_SGBRG10DPCM8,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
32362306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_SGRBG10DPCM8,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
32462306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_SRGGB10DPCM8,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
32562306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_SBGGR12,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
32662306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_SGBRG12,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
32762306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_SGRBG12,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
32862306a36Sopenharmony_ci		{ .format = V4L2_PIX_FMT_SRGGB12,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
32962306a36Sopenharmony_ci	};
33062306a36Sopenharmony_ci	unsigned int i;
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(formats); ++i)
33362306a36Sopenharmony_ci		if (formats[i].format == format)
33462306a36Sopenharmony_ci			return &formats[i];
33562306a36Sopenharmony_ci	return NULL;
33662306a36Sopenharmony_ci}
33762306a36Sopenharmony_ciEXPORT_SYMBOL(v4l2_format_info);
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_cistatic inline unsigned int v4l2_format_block_width(const struct v4l2_format_info *info, int plane)
34062306a36Sopenharmony_ci{
34162306a36Sopenharmony_ci	if (!info->block_w[plane])
34262306a36Sopenharmony_ci		return 1;
34362306a36Sopenharmony_ci	return info->block_w[plane];
34462306a36Sopenharmony_ci}
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_cistatic inline unsigned int v4l2_format_block_height(const struct v4l2_format_info *info, int plane)
34762306a36Sopenharmony_ci{
34862306a36Sopenharmony_ci	if (!info->block_h[plane])
34962306a36Sopenharmony_ci		return 1;
35062306a36Sopenharmony_ci	return info->block_h[plane];
35162306a36Sopenharmony_ci}
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_civoid v4l2_apply_frmsize_constraints(u32 *width, u32 *height,
35462306a36Sopenharmony_ci				    const struct v4l2_frmsize_stepwise *frmsize)
35562306a36Sopenharmony_ci{
35662306a36Sopenharmony_ci	if (!frmsize)
35762306a36Sopenharmony_ci		return;
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci	/*
36062306a36Sopenharmony_ci	 * Clamp width/height to meet min/max constraints and round it up to
36162306a36Sopenharmony_ci	 * macroblock alignment.
36262306a36Sopenharmony_ci	 */
36362306a36Sopenharmony_ci	*width = clamp_roundup(*width, frmsize->min_width, frmsize->max_width,
36462306a36Sopenharmony_ci			       frmsize->step_width);
36562306a36Sopenharmony_ci	*height = clamp_roundup(*height, frmsize->min_height, frmsize->max_height,
36662306a36Sopenharmony_ci				frmsize->step_height);
36762306a36Sopenharmony_ci}
36862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(v4l2_apply_frmsize_constraints);
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_ciint v4l2_fill_pixfmt_mp(struct v4l2_pix_format_mplane *pixfmt,
37162306a36Sopenharmony_ci			u32 pixelformat, u32 width, u32 height)
37262306a36Sopenharmony_ci{
37362306a36Sopenharmony_ci	const struct v4l2_format_info *info;
37462306a36Sopenharmony_ci	struct v4l2_plane_pix_format *plane;
37562306a36Sopenharmony_ci	int i;
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci	info = v4l2_format_info(pixelformat);
37862306a36Sopenharmony_ci	if (!info)
37962306a36Sopenharmony_ci		return -EINVAL;
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ci	pixfmt->width = width;
38262306a36Sopenharmony_ci	pixfmt->height = height;
38362306a36Sopenharmony_ci	pixfmt->pixelformat = pixelformat;
38462306a36Sopenharmony_ci	pixfmt->num_planes = info->mem_planes;
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci	if (info->mem_planes == 1) {
38762306a36Sopenharmony_ci		plane = &pixfmt->plane_fmt[0];
38862306a36Sopenharmony_ci		plane->bytesperline = ALIGN(width, v4l2_format_block_width(info, 0)) * info->bpp[0] / info->bpp_div[0];
38962306a36Sopenharmony_ci		plane->sizeimage = 0;
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci		for (i = 0; i < info->comp_planes; i++) {
39262306a36Sopenharmony_ci			unsigned int hdiv = (i == 0) ? 1 : info->hdiv;
39362306a36Sopenharmony_ci			unsigned int vdiv = (i == 0) ? 1 : info->vdiv;
39462306a36Sopenharmony_ci			unsigned int aligned_width;
39562306a36Sopenharmony_ci			unsigned int aligned_height;
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci			aligned_width = ALIGN(width, v4l2_format_block_width(info, i));
39862306a36Sopenharmony_ci			aligned_height = ALIGN(height, v4l2_format_block_height(info, i));
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_ci			plane->sizeimage += info->bpp[i] *
40162306a36Sopenharmony_ci				DIV_ROUND_UP(aligned_width, hdiv) *
40262306a36Sopenharmony_ci				DIV_ROUND_UP(aligned_height, vdiv) / info->bpp_div[i];
40362306a36Sopenharmony_ci		}
40462306a36Sopenharmony_ci	} else {
40562306a36Sopenharmony_ci		for (i = 0; i < info->comp_planes; i++) {
40662306a36Sopenharmony_ci			unsigned int hdiv = (i == 0) ? 1 : info->hdiv;
40762306a36Sopenharmony_ci			unsigned int vdiv = (i == 0) ? 1 : info->vdiv;
40862306a36Sopenharmony_ci			unsigned int aligned_width;
40962306a36Sopenharmony_ci			unsigned int aligned_height;
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_ci			aligned_width = ALIGN(width, v4l2_format_block_width(info, i));
41262306a36Sopenharmony_ci			aligned_height = ALIGN(height, v4l2_format_block_height(info, i));
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_ci			plane = &pixfmt->plane_fmt[i];
41562306a36Sopenharmony_ci			plane->bytesperline =
41662306a36Sopenharmony_ci				info->bpp[i] * DIV_ROUND_UP(aligned_width, hdiv) / info->bpp_div[i];
41762306a36Sopenharmony_ci			plane->sizeimage =
41862306a36Sopenharmony_ci				plane->bytesperline * DIV_ROUND_UP(aligned_height, vdiv);
41962306a36Sopenharmony_ci		}
42062306a36Sopenharmony_ci	}
42162306a36Sopenharmony_ci	return 0;
42262306a36Sopenharmony_ci}
42362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(v4l2_fill_pixfmt_mp);
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ciint v4l2_fill_pixfmt(struct v4l2_pix_format *pixfmt, u32 pixelformat,
42662306a36Sopenharmony_ci		     u32 width, u32 height)
42762306a36Sopenharmony_ci{
42862306a36Sopenharmony_ci	const struct v4l2_format_info *info;
42962306a36Sopenharmony_ci	int i;
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci	info = v4l2_format_info(pixelformat);
43262306a36Sopenharmony_ci	if (!info)
43362306a36Sopenharmony_ci		return -EINVAL;
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_ci	/* Single planar API cannot be used for multi plane formats. */
43662306a36Sopenharmony_ci	if (info->mem_planes > 1)
43762306a36Sopenharmony_ci		return -EINVAL;
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci	pixfmt->width = width;
44062306a36Sopenharmony_ci	pixfmt->height = height;
44162306a36Sopenharmony_ci	pixfmt->pixelformat = pixelformat;
44262306a36Sopenharmony_ci	pixfmt->bytesperline = ALIGN(width, v4l2_format_block_width(info, 0)) * info->bpp[0] / info->bpp_div[0];
44362306a36Sopenharmony_ci	pixfmt->sizeimage = 0;
44462306a36Sopenharmony_ci
44562306a36Sopenharmony_ci	for (i = 0; i < info->comp_planes; i++) {
44662306a36Sopenharmony_ci		unsigned int hdiv = (i == 0) ? 1 : info->hdiv;
44762306a36Sopenharmony_ci		unsigned int vdiv = (i == 0) ? 1 : info->vdiv;
44862306a36Sopenharmony_ci		unsigned int aligned_width;
44962306a36Sopenharmony_ci		unsigned int aligned_height;
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_ci		aligned_width = ALIGN(width, v4l2_format_block_width(info, i));
45262306a36Sopenharmony_ci		aligned_height = ALIGN(height, v4l2_format_block_height(info, i));
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci		pixfmt->sizeimage += info->bpp[i] *
45562306a36Sopenharmony_ci			DIV_ROUND_UP(aligned_width, hdiv) *
45662306a36Sopenharmony_ci			DIV_ROUND_UP(aligned_height, vdiv) / info->bpp_div[i];
45762306a36Sopenharmony_ci	}
45862306a36Sopenharmony_ci	return 0;
45962306a36Sopenharmony_ci}
46062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(v4l2_fill_pixfmt);
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_cis64 v4l2_get_link_freq(struct v4l2_ctrl_handler *handler, unsigned int mul,
46362306a36Sopenharmony_ci		       unsigned int div)
46462306a36Sopenharmony_ci{
46562306a36Sopenharmony_ci	struct v4l2_ctrl *ctrl;
46662306a36Sopenharmony_ci	s64 freq;
46762306a36Sopenharmony_ci
46862306a36Sopenharmony_ci	ctrl = v4l2_ctrl_find(handler, V4L2_CID_LINK_FREQ);
46962306a36Sopenharmony_ci	if (ctrl) {
47062306a36Sopenharmony_ci		struct v4l2_querymenu qm = { .id = V4L2_CID_LINK_FREQ };
47162306a36Sopenharmony_ci		int ret;
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_ci		qm.index = v4l2_ctrl_g_ctrl(ctrl);
47462306a36Sopenharmony_ci
47562306a36Sopenharmony_ci		ret = v4l2_querymenu(handler, &qm);
47662306a36Sopenharmony_ci		if (ret)
47762306a36Sopenharmony_ci			return -ENOENT;
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_ci		freq = qm.value;
48062306a36Sopenharmony_ci	} else {
48162306a36Sopenharmony_ci		if (!mul || !div)
48262306a36Sopenharmony_ci			return -ENOENT;
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_ci		ctrl = v4l2_ctrl_find(handler, V4L2_CID_PIXEL_RATE);
48562306a36Sopenharmony_ci		if (!ctrl)
48662306a36Sopenharmony_ci			return -ENOENT;
48762306a36Sopenharmony_ci
48862306a36Sopenharmony_ci		freq = div_u64(v4l2_ctrl_g_ctrl_int64(ctrl) * mul, div);
48962306a36Sopenharmony_ci
49062306a36Sopenharmony_ci		pr_warn("%s: Link frequency estimated using pixel rate: result might be inaccurate\n",
49162306a36Sopenharmony_ci			__func__);
49262306a36Sopenharmony_ci		pr_warn("%s: Consider implementing support for V4L2_CID_LINK_FREQ in the transmitter driver\n",
49362306a36Sopenharmony_ci			__func__);
49462306a36Sopenharmony_ci	}
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_ci	return freq > 0 ? freq : -EINVAL;
49762306a36Sopenharmony_ci}
49862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(v4l2_get_link_freq);
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_ci/*
50162306a36Sopenharmony_ci * Simplify a fraction using a simple continued fraction decomposition. The
50262306a36Sopenharmony_ci * idea here is to convert fractions such as 333333/10000000 to 1/30 using
50362306a36Sopenharmony_ci * 32 bit arithmetic only. The algorithm is not perfect and relies upon two
50462306a36Sopenharmony_ci * arbitrary parameters to remove non-significative terms from the simple
50562306a36Sopenharmony_ci * continued fraction decomposition. Using 8 and 333 for n_terms and threshold
50662306a36Sopenharmony_ci * respectively seems to give nice results.
50762306a36Sopenharmony_ci */
50862306a36Sopenharmony_civoid v4l2_simplify_fraction(u32 *numerator, u32 *denominator,
50962306a36Sopenharmony_ci		unsigned int n_terms, unsigned int threshold)
51062306a36Sopenharmony_ci{
51162306a36Sopenharmony_ci	u32 *an;
51262306a36Sopenharmony_ci	u32 x, y, r;
51362306a36Sopenharmony_ci	unsigned int i, n;
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_ci	an = kmalloc_array(n_terms, sizeof(*an), GFP_KERNEL);
51662306a36Sopenharmony_ci	if (an == NULL)
51762306a36Sopenharmony_ci		return;
51862306a36Sopenharmony_ci
51962306a36Sopenharmony_ci	/*
52062306a36Sopenharmony_ci	 * Convert the fraction to a simple continued fraction. See
52162306a36Sopenharmony_ci	 * https://en.wikipedia.org/wiki/Continued_fraction
52262306a36Sopenharmony_ci	 * Stop if the current term is bigger than or equal to the given
52362306a36Sopenharmony_ci	 * threshold.
52462306a36Sopenharmony_ci	 */
52562306a36Sopenharmony_ci	x = *numerator;
52662306a36Sopenharmony_ci	y = *denominator;
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_ci	for (n = 0; n < n_terms && y != 0; ++n) {
52962306a36Sopenharmony_ci		an[n] = x / y;
53062306a36Sopenharmony_ci		if (an[n] >= threshold) {
53162306a36Sopenharmony_ci			if (n < 2)
53262306a36Sopenharmony_ci				n++;
53362306a36Sopenharmony_ci			break;
53462306a36Sopenharmony_ci		}
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_ci		r = x - an[n] * y;
53762306a36Sopenharmony_ci		x = y;
53862306a36Sopenharmony_ci		y = r;
53962306a36Sopenharmony_ci	}
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_ci	/* Expand the simple continued fraction back to an integer fraction. */
54262306a36Sopenharmony_ci	x = 0;
54362306a36Sopenharmony_ci	y = 1;
54462306a36Sopenharmony_ci
54562306a36Sopenharmony_ci	for (i = n; i > 0; --i) {
54662306a36Sopenharmony_ci		r = y;
54762306a36Sopenharmony_ci		y = an[i-1] * y + x;
54862306a36Sopenharmony_ci		x = r;
54962306a36Sopenharmony_ci	}
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_ci	*numerator = y;
55262306a36Sopenharmony_ci	*denominator = x;
55362306a36Sopenharmony_ci	kfree(an);
55462306a36Sopenharmony_ci}
55562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(v4l2_simplify_fraction);
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ci/*
55862306a36Sopenharmony_ci * Convert a fraction to a frame interval in 100ns multiples. The idea here is
55962306a36Sopenharmony_ci * to compute numerator / denominator * 10000000 using 32 bit fixed point
56062306a36Sopenharmony_ci * arithmetic only.
56162306a36Sopenharmony_ci */
56262306a36Sopenharmony_ciu32 v4l2_fraction_to_interval(u32 numerator, u32 denominator)
56362306a36Sopenharmony_ci{
56462306a36Sopenharmony_ci	u32 multiplier;
56562306a36Sopenharmony_ci
56662306a36Sopenharmony_ci	/* Saturate the result if the operation would overflow. */
56762306a36Sopenharmony_ci	if (denominator == 0 ||
56862306a36Sopenharmony_ci	    numerator/denominator >= ((u32)-1)/10000000)
56962306a36Sopenharmony_ci		return (u32)-1;
57062306a36Sopenharmony_ci
57162306a36Sopenharmony_ci	/*
57262306a36Sopenharmony_ci	 * Divide both the denominator and the multiplier by two until
57362306a36Sopenharmony_ci	 * numerator * multiplier doesn't overflow. If anyone knows a better
57462306a36Sopenharmony_ci	 * algorithm please let me know.
57562306a36Sopenharmony_ci	 */
57662306a36Sopenharmony_ci	multiplier = 10000000;
57762306a36Sopenharmony_ci	while (numerator > ((u32)-1)/multiplier) {
57862306a36Sopenharmony_ci		multiplier /= 2;
57962306a36Sopenharmony_ci		denominator /= 2;
58062306a36Sopenharmony_ci	}
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_ci	return denominator ? numerator * multiplier / denominator : 0;
58362306a36Sopenharmony_ci}
58462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(v4l2_fraction_to_interval);
585