File Index
Files and directories
Sign in
FILE

v4l2-common.c

File preview with syntax highlighting.

linux-6.19.14/drivers/media/v4l2-core/v4l2-common.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 *	Video for Linux Two
  4 *
  5 *	A generic video device interface for the LINUX operating system
  6 *	using a set of device structures/vectors for low level operations.
  7 *
  8 *	This file replaces the videodev.c file that comes with the
  9 *	regular kernel distribution.
 10 *
 11 * Author:	Bill Dirks <bill@thedirks.org>
 12 *		based on code by Alan Cox, <alan@cymru.net>
 13 */
 14
 15/*
 16 * Video capture interface for Linux
 17 *
 18 *	A generic video device interface for the LINUX operating system
 19 *	using a set of device structures/vectors for low level operations.
 20 *
 21 * Author:	Alan Cox, <alan@lxorguk.ukuu.org.uk>
 22 *
 23 * Fixes:
 24 */
 25
 26/*
 27 * Video4linux 1/2 integration by Justin Schoeman
 28 * <justin@suntiger.ee.up.ac.za>
 29 * 2.4 PROCFS support ported from 2.4 kernels by
 30 *  Iñaki García Etxebarria <garetxe@euskalnet.net>
 31 * Makefile fix by "W. Michael Petullo" <mike@flyn.org>
 32 * 2.4 devfs support ported from 2.4 kernels by
 33 *  Dan Merillat <dan@merillat.org>
 34 * Added Gerd Knorrs v4l1 enhancements (Justin Schoeman)
 35 */
 36
 37#include <linux/clk.h>
 38#include <linux/clkdev.h>
 39#include <linux/clk-provider.h>
 40#include <linux/module.h>
 41#include <linux/types.h>
 42#include <linux/kernel.h>
 43#include <linux/mm.h>
 44#include <linux/string.h>
 45#include <linux/errno.h>
 46#include <linux/uaccess.h>
 47#include <asm/io.h>
 48#include <asm/div64.h>
 49#include <media/v4l2-common.h>
 50#include <media/v4l2-device.h>
 51#include <media/v4l2-ctrls.h>
 52
 53#include <linux/videodev2.h>
 54
 55/*
 56 *
 57 *	V 4 L 2   D R I V E R   H E L P E R   A P I
 58 *
 59 */
 60
 61/*
 62 *  Video Standard Operations (contributed by Michael Schimek)
 63 */
 64
 65/* Helper functions for control handling			     */
 66
 67/* Fill in a struct v4l2_queryctrl */
 68int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 _min, s32 _max, s32 _step, s32 _def)
 69{
 70	const char *name;
 71	s64 min = _min;
 72	s64 max = _max;
 73	u64 step = _step;
 74	s64 def = _def;
 75
 76	v4l2_ctrl_fill(qctrl->id, &name, &qctrl->type,
 77		       &min, &max, &step, &def, &qctrl->flags);
 78
 79	if (name == NULL)
 80		return -EINVAL;
 81
 82	qctrl->minimum = min;
 83	qctrl->maximum = max;
 84	qctrl->step = step;
 85	qctrl->default_value = def;
 86	qctrl->reserved[0] = qctrl->reserved[1] = 0;
 87	strscpy(qctrl->name, name, sizeof(qctrl->name));
 88	return 0;
 89}
 90EXPORT_SYMBOL(v4l2_ctrl_query_fill);
 91
 92/* Clamp x to be between min and max, aligned to a multiple of 2^align.  min
 93 * and max don't have to be aligned, but there must be at least one valid
 94 * value.  E.g., min=17,max=31,align=4 is not allowed as there are no multiples
 95 * of 16 between 17 and 31.  */
 96static unsigned int clamp_align(unsigned int x, unsigned int min,
 97				unsigned int max, unsigned int align)
 98{
 99	/* Bits that must be zero to be aligned */
100	unsigned int mask = ~((1 << align) - 1);
101
102	/* Clamp to aligned min and max */
103	x = clamp(x, (min + ~mask) & mask, max & mask);
104
105	/* Round to nearest aligned value */
106	if (align)
107		x = (x + (1 << (align - 1))) & mask;
108
109	return x;
110}
111
112static unsigned int clamp_roundup(unsigned int x, unsigned int min,
113				   unsigned int max, unsigned int alignment)
114{
115	x = clamp(x, min, max);
116	if (alignment)
117		x = round_up(x, alignment);
118
119	return x;
120}
121
122void v4l_bound_align_image(u32 *w, unsigned int wmin, unsigned int wmax,
123			   unsigned int walign,
124			   u32 *h, unsigned int hmin, unsigned int hmax,
125			   unsigned int halign, unsigned int salign)
126{
127	*w = clamp_align(*w, wmin, wmax, walign);
128	*h = clamp_align(*h, hmin, hmax, halign);
129
130	/* Usually we don't need to align the size and are done now. */
131	if (!salign)
132		return;
133
134	/* How much alignment do we have? */
135	walign = __ffs(*w);
136	halign = __ffs(*h);
137	/* Enough to satisfy the image alignment? */
138	if (walign + halign < salign) {
139		/* Max walign where there is still a valid width */
140		unsigned int wmaxa = __fls(wmax ^ (wmin - 1));
141		/* Max halign where there is still a valid height */
142		unsigned int hmaxa = __fls(hmax ^ (hmin - 1));
143
144		/* up the smaller alignment until we have enough */
145		do {
146			if (halign >= hmaxa ||
147			    (walign <= halign && walign < wmaxa)) {
148				*w = clamp_align(*w, wmin, wmax, walign + 1);
149				walign = __ffs(*w);
150			} else {
151				*h = clamp_align(*h, hmin, hmax, halign + 1);
152				halign = __ffs(*h);
153			}
154		} while (halign + walign < salign);
155	}
156}
157EXPORT_SYMBOL_GPL(v4l_bound_align_image);
158
159const void *
160__v4l2_find_nearest_size_conditional(const void *array, size_t array_size,
161				     size_t entry_size, size_t width_offset,
162				     size_t height_offset, s32 width,
163				     s32 height,
164				     bool (*func)(const void *array,
165						  size_t index,
166						  const void *context),
167				     const void *context)
168{
169	u32 error, min_error = U32_MAX;
170	const void *best = NULL;
171	size_t i;
172
173	if (!array)
174		return NULL;
175
176	for (i = 0; i < array_size; i++, array += entry_size) {
177		const u32 *entry_width = array + width_offset;
178		const u32 *entry_height = array + height_offset;
179
180		if (func && !func(array, i, context))
181			continue;
182
183		error = abs(*entry_width - width) + abs(*entry_height - height);
184		if (error > min_error)
185			continue;
186
187		min_error = error;
188		best = array;
189		if (!error)
190			break;
191	}
192
193	return best;
194}
195EXPORT_SYMBOL_GPL(__v4l2_find_nearest_size_conditional);
196
197int v4l2_g_parm_cap(struct video_device *vdev,
198		    struct v4l2_subdev *sd, struct v4l2_streamparm *a)
199{
200	struct v4l2_subdev_frame_interval ival = { 0 };
201	int ret;
202
203	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
204	    a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
205		return -EINVAL;
206
207	if (vdev->device_caps & V4L2_CAP_READWRITE)
208		a->parm.capture.readbuffers = 2;
209	if (v4l2_subdev_has_op(sd, pad, get_frame_interval))
210		a->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
211	ret = v4l2_subdev_call_state_active(sd, pad, get_frame_interval, &ival);
212	if (!ret)
213		a->parm.capture.timeperframe = ival.interval;
214	return ret;
215}
216EXPORT_SYMBOL_GPL(v4l2_g_parm_cap);
217
218int v4l2_s_parm_cap(struct video_device *vdev,
219		    struct v4l2_subdev *sd, struct v4l2_streamparm *a)
220{
221	struct v4l2_subdev_frame_interval ival = {
222		.interval = a->parm.capture.timeperframe
223	};
224	int ret;
225
226	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
227	    a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
228		return -EINVAL;
229
230	memset(&a->parm, 0, sizeof(a->parm));
231	if (vdev->device_caps & V4L2_CAP_READWRITE)
232		a->parm.capture.readbuffers = 2;
233	else
234		a->parm.capture.readbuffers = 0;
235
236	if (v4l2_subdev_has_op(sd, pad, get_frame_interval))
237		a->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
238	ret = v4l2_subdev_call_state_active(sd, pad, set_frame_interval, &ival);
239	if (!ret)
240		a->parm.capture.timeperframe = ival.interval;
241	return ret;
242}
243EXPORT_SYMBOL_GPL(v4l2_s_parm_cap);
244
245const struct v4l2_format_info *v4l2_format_info(u32 format)
246{
247	static const struct v4l2_format_info formats[] = {
248		/* RGB formats */
249		{ .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 },
250		{ .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 },
251		{ .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 },
252		{ .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 },
253		{ .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 },
254		{ .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 },
255		{ .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 },
256		{ .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 },
257		{ .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 },
258		{ .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 },
259		{ .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 },
260		{ .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 },
261		{ .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 },
262		{ .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 },
263		{ .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 },
264		{ .format = V4L2_PIX_FMT_RGB565X, .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 },
265		{ .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 },
266		{ .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 },
267		{ .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 },
268		{ .format = V4L2_PIX_FMT_BGR48, .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 },
269		{ .format = V4L2_PIX_FMT_RGB48, .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 },
270		{ .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 },
271		{ .format = V4L2_PIX_FMT_RGBA1010102, .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 },
272		{ .format = V4L2_PIX_FMT_RGBX1010102, .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 },
273		{ .format = V4L2_PIX_FMT_ARGB2101010, .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 },
274
275		/* YUV packed formats */
276		{ .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 },
277		{ .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 },
278		{ .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 },
279		{ .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 },
280		{ .format = V4L2_PIX_FMT_Y210,    .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 },
281		{ .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 },
282		{ .format = V4L2_PIX_FMT_Y216,    .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 },
283		{ .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 },
284		{ .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,
285		  .block_w = { 16, 8, 0, 0 }, .block_h = { 32, 16, 0, 0 }},
286		{ .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,
287		  .block_w = { 16, 8, 0, 0 }, .block_h = { 32, 16, 0, 0 }},
288
289		/* YUV planar formats */
290		{ .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 },
291		{ .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 },
292		{ .format = V4L2_PIX_FMT_NV15,    .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 },
293		{ .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 },
294		{ .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 },
295		{ .format = V4L2_PIX_FMT_NV20,    .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 = 1 },
296		{ .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 },
297		{ .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 },
298		{ .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 },
299		{ .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 },
300
301		{ .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 },
302		{ .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 },
303		{ .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 },
304		{ .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 },
305		{ .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 },
306		{ .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 },
307		{ .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 },
308
309		/* Tiled YUV formats */
310		{ .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 },
311		{ .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,
312		  .block_w = { 4, 2, 0, 0 }, .block_h = { 1, 1, 0, 0 }},
313		{ .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 },
314
315		/* YUV planar formats, non contiguous variant */
316		{ .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 },
317		{ .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 },
318		{ .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 },
319		{ .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 },
320		{ .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 },
321		{ .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 },
322
323		{ .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 },
324		{ .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 },
325		{ .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 },
326		{ .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 },
327		{ .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 },
328
329		/* Tiled YUV formats, non contiguous variant */
330		{ .format = V4L2_PIX_FMT_NV12MT,        .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,
331		  .block_w = { 64, 32, 0, 0 },	.block_h = { 32, 16, 0, 0 }},
332		{ .format = V4L2_PIX_FMT_NV12MT_16X16,  .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,
333		  .block_w = { 16,  8, 0, 0 },	.block_h = { 16,  8, 0, 0 }},
334
335		/* Bayer RGB formats */
336		{ .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 },
337		{ .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 },
338		{ .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 },
339		{ .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 },
340		{ .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 },
341		{ .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 },
342		{ .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 },
343		{ .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 },
344		{ .format = V4L2_PIX_FMT_SBGGR10P,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 5, 0, 0, 0 }, .bpp_div = { 4, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
345		{ .format = V4L2_PIX_FMT_SGBRG10P,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 5, 0, 0, 0 }, .bpp_div = { 4, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
346		{ .format = V4L2_PIX_FMT_SGRBG10P,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 5, 0, 0, 0 }, .bpp_div = { 4, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
347		{ .format = V4L2_PIX_FMT_SRGGB10P,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 5, 0, 0, 0 }, .bpp_div = { 4, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
348		{ .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 },
349		{ .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 },
350		{ .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 },
351		{ .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 },
352		{ .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 },
353		{ .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 },
354		{ .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 },
355		{ .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 },
356		{ .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 },
357		{ .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 },
358		{ .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 },
359		{ .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 },
360		{ .format = V4L2_PIX_FMT_SBGGR12P,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .bpp_div = { 2, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
361		{ .format = V4L2_PIX_FMT_SGBRG12P,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .bpp_div = { 2, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
362		{ .format = V4L2_PIX_FMT_SGRBG12P,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .bpp_div = { 2, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
363		{ .format = V4L2_PIX_FMT_SRGGB12P,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .bpp_div = { 2, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
364		{ .format = V4L2_PIX_FMT_SBGGR14,	.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 },
365		{ .format = V4L2_PIX_FMT_SGBRG14,	.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 },
366		{ .format = V4L2_PIX_FMT_SGRBG14,	.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 },
367		{ .format = V4L2_PIX_FMT_SRGGB14,	.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 },
368		{ .format = V4L2_PIX_FMT_SBGGR14P,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 7, 0, 0, 0 }, .bpp_div = { 4, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
369		{ .format = V4L2_PIX_FMT_SGBRG14P,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 7, 0, 0, 0 }, .bpp_div = { 4, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
370		{ .format = V4L2_PIX_FMT_SGRBG14P,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 7, 0, 0, 0 }, .bpp_div = { 4, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
371		{ .format = V4L2_PIX_FMT_SRGGB14P,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 7, 0, 0, 0 }, .bpp_div = { 4, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
372		{ .format = V4L2_PIX_FMT_SBGGR16,	.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 },
373		{ .format = V4L2_PIX_FMT_SGBRG16,	.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 },
374		{ .format = V4L2_PIX_FMT_SGRBG16,	.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 },
375		{ .format = V4L2_PIX_FMT_SRGGB16,	.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 },
376
377		/* Renesas Camera Data Receiver Unit formats, bayer order agnostic */
378		{ .format = V4L2_PIX_FMT_RAW_CRU10,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 8, 0, 0, 0 }, .bpp_div = { 6, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
379		{ .format = V4L2_PIX_FMT_RAW_CRU12,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 8, 0, 0, 0 }, .bpp_div = { 5, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
380		{ .format = V4L2_PIX_FMT_RAW_CRU14,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 8, 0, 0, 0 }, .bpp_div = { 4, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
381		{ .format = V4L2_PIX_FMT_RAW_CRU20,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 8, 0, 0, 0 }, .bpp_div = { 3, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
382	};
383	unsigned int i;
384
385	for (i = 0; i < ARRAY_SIZE(formats); ++i)
386		if (formats[i].format == format)
387			return &formats[i];
388	return NULL;
389}
390EXPORT_SYMBOL(v4l2_format_info);
391
392static inline unsigned int v4l2_format_block_width(const struct v4l2_format_info *info, int plane)
393{
394	if (!info->block_w[plane])
395		return 1;
396	return info->block_w[plane];
397}
398
399static inline unsigned int v4l2_format_block_height(const struct v4l2_format_info *info, int plane)
400{
401	if (!info->block_h[plane])
402		return 1;
403	return info->block_h[plane];
404}
405
406static inline unsigned int v4l2_format_plane_stride(const struct v4l2_format_info *info, int plane,
407						    unsigned int width)
408{
409	unsigned int hdiv = plane ? info->hdiv : 1;
410	unsigned int aligned_width =
411		ALIGN(width, v4l2_format_block_width(info, plane));
412
413	return DIV_ROUND_UP(aligned_width, hdiv) *
414	       info->bpp[plane] / info->bpp_div[plane];
415}
416
417static inline unsigned int v4l2_format_plane_height(const struct v4l2_format_info *info, int plane,
418						    unsigned int height)
419{
420	unsigned int vdiv = plane ? info->vdiv : 1;
421	unsigned int aligned_height =
422		ALIGN(height, v4l2_format_block_height(info, plane));
423
424	return DIV_ROUND_UP(aligned_height, vdiv);
425}
426
427static inline unsigned int v4l2_format_plane_size(const struct v4l2_format_info *info, int plane,
428						  unsigned int width, unsigned int height)
429{
430	return v4l2_format_plane_stride(info, plane, width) *
431	       v4l2_format_plane_height(info, plane, height);
432}
433
434void v4l2_apply_frmsize_constraints(u32 *width, u32 *height,
435				    const struct v4l2_frmsize_stepwise *frmsize)
436{
437	if (!frmsize)
438		return;
439
440	/*
441	 * Clamp width/height to meet min/max constraints and round it up to
442	 * macroblock alignment.
443	 */
444	*width = clamp_roundup(*width, frmsize->min_width, frmsize->max_width,
445			       frmsize->step_width);
446	*height = clamp_roundup(*height, frmsize->min_height, frmsize->max_height,
447				frmsize->step_height);
448}
449EXPORT_SYMBOL_GPL(v4l2_apply_frmsize_constraints);
450
451int v4l2_fill_pixfmt_mp(struct v4l2_pix_format_mplane *pixfmt,
452			u32 pixelformat, u32 width, u32 height)
453{
454	const struct v4l2_format_info *info;
455	struct v4l2_plane_pix_format *plane;
456	int i;
457
458	info = v4l2_format_info(pixelformat);
459	if (!info)
460		return -EINVAL;
461
462	pixfmt->width = width;
463	pixfmt->height = height;
464	pixfmt->pixelformat = pixelformat;
465	pixfmt->num_planes = info->mem_planes;
466
467	if (info->mem_planes == 1) {
468		plane = &pixfmt->plane_fmt[0];
469		plane->bytesperline = v4l2_format_plane_stride(info, 0, width);
470		plane->sizeimage = 0;
471
472		for (i = 0; i < info->comp_planes; i++)
473			plane->sizeimage +=
474				v4l2_format_plane_size(info, i, width, height);
475	} else {
476		for (i = 0; i < info->comp_planes; i++) {
477			plane = &pixfmt->plane_fmt[i];
478			plane->bytesperline =
479				v4l2_format_plane_stride(info, i, width);
480			plane->sizeimage = plane->bytesperline *
481				v4l2_format_plane_height(info, i, height);
482		}
483	}
484	return 0;
485}
486EXPORT_SYMBOL_GPL(v4l2_fill_pixfmt_mp);
487
488int v4l2_fill_pixfmt(struct v4l2_pix_format *pixfmt, u32 pixelformat,
489		     u32 width, u32 height)
490{
491	const struct v4l2_format_info *info;
492	int i;
493
494	info = v4l2_format_info(pixelformat);
495	if (!info)
496		return -EINVAL;
497
498	/* Single planar API cannot be used for multi plane formats. */
499	if (info->mem_planes > 1)
500		return -EINVAL;
501
502	pixfmt->width = width;
503	pixfmt->height = height;
504	pixfmt->pixelformat = pixelformat;
505	pixfmt->bytesperline = v4l2_format_plane_stride(info, 0, width);
506	pixfmt->sizeimage = 0;
507
508	for (i = 0; i < info->comp_planes; i++)
509		pixfmt->sizeimage +=
510			v4l2_format_plane_size(info, i, width, height);
511	return 0;
512}
513EXPORT_SYMBOL_GPL(v4l2_fill_pixfmt);
514
515#ifdef CONFIG_MEDIA_CONTROLLER
516static s64 v4l2_get_link_freq_ctrl(struct v4l2_ctrl_handler *handler,
517				   unsigned int mul, unsigned int div)
518{
519	struct v4l2_ctrl *ctrl;
520	s64 freq;
521
522	ctrl = v4l2_ctrl_find(handler, V4L2_CID_LINK_FREQ);
523	if (ctrl) {
524		struct v4l2_querymenu qm = { .id = V4L2_CID_LINK_FREQ };
525		int ret;
526
527		qm.index = v4l2_ctrl_g_ctrl(ctrl);
528
529		ret = v4l2_querymenu(handler, &qm);
530		if (ret)
531			return -ENOENT;
532
533		freq = qm.value;
534	} else {
535		if (!mul || !div)
536			return -ENOENT;
537
538		ctrl = v4l2_ctrl_find(handler, V4L2_CID_PIXEL_RATE);
539		if (!ctrl)
540			return -ENOENT;
541
542		freq = div_u64(v4l2_ctrl_g_ctrl_int64(ctrl) * mul, div);
543
544		pr_warn_once("%s: Link frequency estimated using pixel rate: result might be inaccurate\n",
545			     __func__);
546		pr_warn_once("%s: Consider implementing support for V4L2_CID_LINK_FREQ in the transmitter driver\n",
547			     __func__);
548	}
549
550	return freq > 0 ? freq : -EINVAL;
551}
552
553s64 v4l2_get_link_freq(const struct media_pad *pad, unsigned int mul,
554		       unsigned int div)
555{
556	struct v4l2_mbus_config mbus_config = {};
557	struct v4l2_subdev *sd;
558	int ret;
559
560	sd = media_entity_to_v4l2_subdev(pad->entity);
561	ret = v4l2_subdev_call(sd, pad, get_mbus_config, pad->index,
562			       &mbus_config);
563	if (ret < 0 && ret != -ENOIOCTLCMD)
564		return ret;
565
566	if (mbus_config.link_freq)
567		return mbus_config.link_freq;
568
569	/*
570	 * Fall back to using the link frequency control if the media bus config
571	 * doesn't provide a link frequency.
572	 */
573	return v4l2_get_link_freq_ctrl(sd->ctrl_handler, mul, div);
574}
575EXPORT_SYMBOL_GPL(v4l2_get_link_freq);
576
577int v4l2_get_active_data_lanes(const struct media_pad *pad,
578			       unsigned int max_data_lanes)
579{
580	struct v4l2_mbus_config mbus_config = {};
581	struct v4l2_subdev *sd;
582	unsigned int lanes;
583	int ret;
584
585	sd = media_entity_to_v4l2_subdev(pad->entity);
586	ret = v4l2_subdev_call(sd, pad, get_mbus_config, pad->index,
587			       &mbus_config);
588	if (ret < 0 && ret != -ENOIOCTLCMD)
589		return ret;
590
591	/* This relies on the mbus_config being zeroed at init time */
592	lanes = mbus_config.bus.mipi_csi2.num_data_lanes;
593	if (!lanes)
594		return max_data_lanes;
595
596	if (lanes > max_data_lanes) {
597		dev_dbg(sd->dev, "Active data lanes (%u) exceeds max (%u)\n",
598			lanes, max_data_lanes);
599		return -EINVAL;
600	}
601
602	return lanes;
603}
604EXPORT_SYMBOL_GPL(v4l2_get_active_data_lanes);
605#endif
606
607/*
608 * Simplify a fraction using a simple continued fraction decomposition. The
609 * idea here is to convert fractions such as 333333/10000000 to 1/30 using
610 * 32 bit arithmetic only. The algorithm is not perfect and relies upon two
611 * arbitrary parameters to remove non-significative terms from the simple
612 * continued fraction decomposition. Using 8 and 333 for n_terms and threshold
613 * respectively seems to give nice results.
614 */
615void v4l2_simplify_fraction(u32 *numerator, u32 *denominator,
616		unsigned int n_terms, unsigned int threshold)
617{
618	u32 *an;
619	u32 x, y, r;
620	unsigned int i, n;
621
622	an = kmalloc_array(n_terms, sizeof(*an), GFP_KERNEL);
623	if (an == NULL)
624		return;
625
626	/*
627	 * Convert the fraction to a simple continued fraction. See
628	 * https://en.wikipedia.org/wiki/Continued_fraction
629	 * Stop if the current term is bigger than or equal to the given
630	 * threshold.
631	 */
632	x = *numerator;
633	y = *denominator;
634
635	for (n = 0; n < n_terms && y != 0; ++n) {
636		an[n] = x / y;
637		if (an[n] >= threshold) {
638			if (n < 2)
639				n++;
640			break;
641		}
642
643		r = x - an[n] * y;
644		x = y;
645		y = r;
646	}
647
648	/* Expand the simple continued fraction back to an integer fraction. */
649	x = 0;
650	y = 1;
651
652	for (i = n; i > 0; --i) {
653		r = y;
654		y = an[i-1] * y + x;
655		x = r;
656	}
657
658	*numerator = y;
659	*denominator = x;
660	kfree(an);
661}
662EXPORT_SYMBOL_GPL(v4l2_simplify_fraction);
663
664/*
665 * Convert a fraction to a frame interval in 100ns multiples. The idea here is
666 * to compute numerator / denominator * 10000000 using 32 bit fixed point
667 * arithmetic only.
668 */
669u32 v4l2_fraction_to_interval(u32 numerator, u32 denominator)
670{
671	u32 multiplier;
672
673	/* Saturate the result if the operation would overflow. */
674	if (denominator == 0 ||
675	    numerator/denominator >= ((u32)-1)/10000000)
676		return (u32)-1;
677
678	/*
679	 * Divide both the denominator and the multiplier by two until
680	 * numerator * multiplier doesn't overflow. If anyone knows a better
681	 * algorithm please let me know.
682	 */
683	multiplier = 10000000;
684	while (numerator > ((u32)-1)/multiplier) {
685		multiplier /= 2;
686		denominator /= 2;
687	}
688
689	return denominator ? numerator * multiplier / denominator : 0;
690}
691EXPORT_SYMBOL_GPL(v4l2_fraction_to_interval);
692
693int v4l2_link_freq_to_bitmap(struct device *dev, const u64 *fw_link_freqs,
694			     unsigned int num_of_fw_link_freqs,
695			     const s64 *driver_link_freqs,
696			     unsigned int num_of_driver_link_freqs,
697			     unsigned long *bitmap)
698{
699	unsigned int i;
700
701	*bitmap = 0;
702
703	if (!num_of_fw_link_freqs) {
704		dev_err(dev, "no link frequencies in firmware\n");
705		return -ENODATA;
706	}
707
708	for (i = 0; i < num_of_fw_link_freqs; i++) {
709		unsigned int j;
710
711		for (j = 0; j < num_of_driver_link_freqs; j++) {
712			if (fw_link_freqs[i] != driver_link_freqs[j])
713				continue;
714
715			dev_dbg(dev, "enabling link frequency %lld Hz\n",
716				driver_link_freqs[j]);
717			*bitmap |= BIT(j);
718			break;
719		}
720	}
721
722	if (!*bitmap) {
723		dev_err(dev, "no matching link frequencies found\n");
724
725		dev_dbg(dev, "specified in firmware:\n");
726		for (i = 0; i < num_of_fw_link_freqs; i++)
727			dev_dbg(dev, "\t%llu Hz\n", fw_link_freqs[i]);
728
729		dev_dbg(dev, "driver supported:\n");
730		for (i = 0; i < num_of_driver_link_freqs; i++)
731			dev_dbg(dev, "\t%lld Hz\n", driver_link_freqs[i]);
732
733		return -ENOENT;
734	}
735
736	return 0;
737}
738EXPORT_SYMBOL_GPL(v4l2_link_freq_to_bitmap);
739
740struct clk *__devm_v4l2_sensor_clk_get(struct device *dev, const char *id,
741				       bool legacy, bool fixed_rate,
742				       unsigned long clk_rate)
743{
744	bool of_node = is_of_node(dev_fwnode(dev));
745	const char *clk_id __free(kfree) = NULL;
746	struct clk_hw *clk_hw;
747	struct clk *clk;
748	u32 rate = clk_rate;
749	int ret = 0;
750
751	clk = devm_clk_get_optional(dev, id);
752	if (IS_ERR(clk))
753		return clk;
754
755	/*
756	 * If the caller didn't request a fixed rate, retrieve it from the
757	 * clock-frequency property. -EINVAL indicates the property is absent,
758	 * and is not a failure. Other errors, or success with a clock-frequency
759	 * value of 0, are hard failures.
760	 */
761	if (!fixed_rate || !clk_rate) {
762		ret = device_property_read_u32(dev, "clock-frequency", &rate);
763		if ((ret && ret != -EINVAL) || (!ret && !rate))
764			return ERR_PTR(-EINVAL);
765	}
766
767	if (clk) {
768		/*
769		 * On non-OF platforms, or when legacy behaviour is requested,
770		 * set the clock rate if a rate has been specified by the caller
771		 * or by the clock-frequency property.
772		 */
773		if (rate && (!of_node || legacy)) {
774			ret = clk_set_rate(clk, rate);
775			if (ret) {
776				dev_err(dev, "Failed to set clock rate: %u\n",
777					rate);
778				return ERR_PTR(ret);
779			}
780		}
781		return clk;
782	}
783
784	/*
785	 * Register a dummy fixed clock on non-OF platforms or when legacy
786	 * behaviour is requested. This required the common clock framework.
787	 */
788	if (!IS_ENABLED(CONFIG_COMMON_CLK) || (of_node && !legacy))
789		return ERR_PTR(-ENOENT);
790
791	/* We need a rate to create a clock. */
792	if (ret)
793		return ERR_PTR(ret == -EINVAL ? -EPROBE_DEFER : ret);
794
795	if (!id) {
796		clk_id = kasprintf(GFP_KERNEL, "clk-%s", dev_name(dev));
797		if (!clk_id)
798			return ERR_PTR(-ENOMEM);
799		id = clk_id;
800	}
801
802	clk_hw = devm_clk_hw_register_fixed_rate(dev, id, NULL, 0, rate);
803	if (IS_ERR(clk_hw))
804		return ERR_CAST(clk_hw);
805
806	return clk_hw->clk;
807}
808EXPORT_SYMBOL_GPL(__devm_v4l2_sensor_clk_get);
~/ Read-only file preview.