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 */
v4l2_ctrl_query_fill(struct v4l2_queryctrl * qctrl,s32 _min,s32 _max,s32 _step,s32 _def)68 int 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 }
90 EXPORT_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. */
clamp_align(unsigned int x,unsigned int min,unsigned int max,unsigned int align)96 static 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
clamp_roundup(unsigned int x,unsigned int min,unsigned int max,unsigned int alignment)112 static 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
v4l_bound_align_image(u32 * w,unsigned int wmin,unsigned int wmax,unsigned int walign,u32 * h,unsigned int hmin,unsigned int hmax,unsigned int halign,unsigned int salign)122 void 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 }
157 EXPORT_SYMBOL_GPL(v4l_bound_align_image);
158
159 const void *
__v4l2_find_nearest_size_conditional(const void * array,size_t array_size,size_t entry_size,size_t width_offset,size_t height_offset,s32 width,s32 height,bool (* func)(const void * array,size_t index,const void * context),const void * context)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 }
195 EXPORT_SYMBOL_GPL(__v4l2_find_nearest_size_conditional);
196
v4l2_g_parm_cap(struct video_device * vdev,struct v4l2_subdev * sd,struct v4l2_streamparm * a)197 int 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 }
216 EXPORT_SYMBOL_GPL(v4l2_g_parm_cap);
217
v4l2_s_parm_cap(struct video_device * vdev,struct v4l2_subdev * sd,struct v4l2_streamparm * a)218 int 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 }
243 EXPORT_SYMBOL_GPL(v4l2_s_parm_cap);
244
v4l2_format_info(u32 format)245 const 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 }
390 EXPORT_SYMBOL(v4l2_format_info);
391
v4l2_format_block_width(const struct v4l2_format_info * info,int plane)392 static 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
v4l2_format_block_height(const struct v4l2_format_info * info,int plane)399 static 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
v4l2_format_plane_stride(const struct v4l2_format_info * info,int plane,unsigned int width)406 static 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
v4l2_format_plane_height(const struct v4l2_format_info * info,int plane,unsigned int height)417 static 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
v4l2_format_plane_size(const struct v4l2_format_info * info,int plane,unsigned int width,unsigned int height)427 static 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
v4l2_apply_frmsize_constraints(u32 * width,u32 * height,const struct v4l2_frmsize_stepwise * frmsize)434 void 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 }
449 EXPORT_SYMBOL_GPL(v4l2_apply_frmsize_constraints);
450
v4l2_fill_pixfmt_mp(struct v4l2_pix_format_mplane * pixfmt,u32 pixelformat,u32 width,u32 height)451 int 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 }
486 EXPORT_SYMBOL_GPL(v4l2_fill_pixfmt_mp);
487
v4l2_fill_pixfmt(struct v4l2_pix_format * pixfmt,u32 pixelformat,u32 width,u32 height)488 int 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 }
513 EXPORT_SYMBOL_GPL(v4l2_fill_pixfmt);
514
515 #ifdef CONFIG_MEDIA_CONTROLLER
v4l2_get_link_freq_ctrl(struct v4l2_ctrl_handler * handler,unsigned int mul,unsigned int div)516 static 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
v4l2_get_link_freq(const struct media_pad * pad,unsigned int mul,unsigned int div)553 s64 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 }
575 EXPORT_SYMBOL_GPL(v4l2_get_link_freq);
576
v4l2_get_active_data_lanes(const struct media_pad * pad,unsigned int max_data_lanes)577 int 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 }
604 EXPORT_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 */
v4l2_simplify_fraction(u32 * numerator,u32 * denominator,unsigned int n_terms,unsigned int threshold)615 void 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 }
662 EXPORT_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 */
v4l2_fraction_to_interval(u32 numerator,u32 denominator)669 u32 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 }
691 EXPORT_SYMBOL_GPL(v4l2_fraction_to_interval);
692
v4l2_link_freq_to_bitmap(struct device * dev,const u64 * fw_link_freqs,unsigned int num_of_fw_link_freqs,const s64 * driver_link_freqs,unsigned int num_of_driver_link_freqs,unsigned long * bitmap)693 int 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 }
738 EXPORT_SYMBOL_GPL(v4l2_link_freq_to_bitmap);
739
__devm_v4l2_sensor_clk_get(struct device * dev,const char * id,bool legacy,bool fixed_rate,unsigned long clk_rate)740 struct 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 }
808 EXPORT_SYMBOL_GPL(__devm_v4l2_sensor_clk_get);
809