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/module.h> 38 #include <linux/types.h> 39 #include <linux/kernel.h> 40 #include <linux/mm.h> 41 #include <linux/string.h> 42 #include <linux/errno.h> 43 #include <linux/uaccess.h> 44 #include <asm/io.h> 45 #include <asm/div64.h> 46 #include <media/v4l2-common.h> 47 #include <media/v4l2-device.h> 48 #include <media/v4l2-ctrls.h> 49 50 #include <linux/videodev2.h> 51 52 /* 53 * 54 * V 4 L 2 D R I V E R H E L P E R A P I 55 * 56 */ 57 58 /* 59 * Video Standard Operations (contributed by Michael Schimek) 60 */ 61 62 /* Helper functions for control handling */ 63 64 /* Fill in a struct v4l2_queryctrl */ 65 int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 _min, s32 _max, s32 _step, s32 _def) 66 { 67 const char *name; 68 s64 min = _min; 69 s64 max = _max; 70 u64 step = _step; 71 s64 def = _def; 72 73 v4l2_ctrl_fill(qctrl->id, &name, &qctrl->type, 74 &min, &max, &step, &def, &qctrl->flags); 75 76 if (name == NULL) 77 return -EINVAL; 78 79 qctrl->minimum = min; 80 qctrl->maximum = max; 81 qctrl->step = step; 82 qctrl->default_value = def; 83 qctrl->reserved[0] = qctrl->reserved[1] = 0; 84 strscpy(qctrl->name, name, sizeof(qctrl->name)); 85 return 0; 86 } 87 EXPORT_SYMBOL(v4l2_ctrl_query_fill); 88 89 /* Clamp x to be between min and max, aligned to a multiple of 2^align. min 90 * and max don't have to be aligned, but there must be at least one valid 91 * value. E.g., min=17,max=31,align=4 is not allowed as there are no multiples 92 * of 16 between 17 and 31. */ 93 static unsigned int clamp_align(unsigned int x, unsigned int min, 94 unsigned int max, unsigned int align) 95 { 96 /* Bits that must be zero to be aligned */ 97 unsigned int mask = ~((1 << align) - 1); 98 99 /* Clamp to aligned min and max */ 100 x = clamp(x, (min + ~mask) & mask, max & mask); 101 102 /* Round to nearest aligned value */ 103 if (align) 104 x = (x + (1 << (align - 1))) & mask; 105 106 return x; 107 } 108 109 static unsigned int clamp_roundup(unsigned int x, unsigned int min, 110 unsigned int max, unsigned int alignment) 111 { 112 x = clamp(x, min, max); 113 if (alignment) 114 x = round_up(x, alignment); 115 116 return x; 117 } 118 119 void v4l_bound_align_image(u32 *w, unsigned int wmin, unsigned int wmax, 120 unsigned int walign, 121 u32 *h, unsigned int hmin, unsigned int hmax, 122 unsigned int halign, unsigned int salign) 123 { 124 *w = clamp_align(*w, wmin, wmax, walign); 125 *h = clamp_align(*h, hmin, hmax, halign); 126 127 /* Usually we don't need to align the size and are done now. */ 128 if (!salign) 129 return; 130 131 /* How much alignment do we have? */ 132 walign = __ffs(*w); 133 halign = __ffs(*h); 134 /* Enough to satisfy the image alignment? */ 135 if (walign + halign < salign) { 136 /* Max walign where there is still a valid width */ 137 unsigned int wmaxa = __fls(wmax ^ (wmin - 1)); 138 /* Max halign where there is still a valid height */ 139 unsigned int hmaxa = __fls(hmax ^ (hmin - 1)); 140 141 /* up the smaller alignment until we have enough */ 142 do { 143 if (halign >= hmaxa || 144 (walign <= halign && walign < wmaxa)) { 145 *w = clamp_align(*w, wmin, wmax, walign + 1); 146 walign = __ffs(*w); 147 } else { 148 *h = clamp_align(*h, hmin, hmax, halign + 1); 149 halign = __ffs(*h); 150 } 151 } while (halign + walign < salign); 152 } 153 } 154 EXPORT_SYMBOL_GPL(v4l_bound_align_image); 155 156 const void * 157 __v4l2_find_nearest_size_conditional(const void *array, size_t array_size, 158 size_t entry_size, size_t width_offset, 159 size_t height_offset, s32 width, 160 s32 height, 161 bool (*func)(const void *array, 162 size_t index, 163 const void *context), 164 const void *context) 165 { 166 u32 error, min_error = U32_MAX; 167 const void *best = NULL; 168 size_t i; 169 170 if (!array) 171 return NULL; 172 173 for (i = 0; i < array_size; i++, array += entry_size) { 174 const u32 *entry_width = array + width_offset; 175 const u32 *entry_height = array + height_offset; 176 177 if (func && !func(array, i, context)) 178 continue; 179 180 error = abs(*entry_width - width) + abs(*entry_height - height); 181 if (error > min_error) 182 continue; 183 184 min_error = error; 185 best = array; 186 if (!error) 187 break; 188 } 189 190 return best; 191 } 192 EXPORT_SYMBOL_GPL(__v4l2_find_nearest_size_conditional); 193 194 int v4l2_g_parm_cap(struct video_device *vdev, 195 struct v4l2_subdev *sd, struct v4l2_streamparm *a) 196 { 197 struct v4l2_subdev_frame_interval ival = { 0 }; 198 int ret; 199 200 if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && 201 a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) 202 return -EINVAL; 203 204 if (vdev->device_caps & V4L2_CAP_READWRITE) 205 a->parm.capture.readbuffers = 2; 206 if (v4l2_subdev_has_op(sd, pad, get_frame_interval)) 207 a->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; 208 ret = v4l2_subdev_call_state_active(sd, pad, get_frame_interval, &ival); 209 if (!ret) 210 a->parm.capture.timeperframe = ival.interval; 211 return ret; 212 } 213 EXPORT_SYMBOL_GPL(v4l2_g_parm_cap); 214 215 int v4l2_s_parm_cap(struct video_device *vdev, 216 struct v4l2_subdev *sd, struct v4l2_streamparm *a) 217 { 218 struct v4l2_subdev_frame_interval ival = { 219 .interval = a->parm.capture.timeperframe 220 }; 221 int ret; 222 223 if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && 224 a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) 225 return -EINVAL; 226 227 memset(&a->parm, 0, sizeof(a->parm)); 228 if (vdev->device_caps & V4L2_CAP_READWRITE) 229 a->parm.capture.readbuffers = 2; 230 else 231 a->parm.capture.readbuffers = 0; 232 233 if (v4l2_subdev_has_op(sd, pad, get_frame_interval)) 234 a->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; 235 ret = v4l2_subdev_call_state_active(sd, pad, set_frame_interval, &ival); 236 if (!ret) 237 a->parm.capture.timeperframe = ival.interval; 238 return ret; 239 } 240 EXPORT_SYMBOL_GPL(v4l2_s_parm_cap); 241 242 const struct v4l2_format_info *v4l2_format_info(u32 format) 243 { 244 static const struct v4l2_format_info formats[] = { 245 /* RGB formats */ 246 { .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 }, 247 { .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 }, 248 { .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 }, 249 { .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 }, 250 { .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 }, 251 { .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 }, 252 { .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 }, 253 { .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 }, 254 { .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 }, 255 { .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 }, 256 { .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 }, 257 { .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 }, 258 { .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 }, 259 { .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 }, 260 { .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 }, 261 { .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 }, 262 { .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 }, 263 { .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 }, 264 { .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 }, 265 { .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 }, 266 { .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 }, 267 { .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 }, 268 { .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 }, 269 { .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 }, 270 { .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 }, 271 272 /* YUV packed formats */ 273 { .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 }, 274 { .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 }, 275 { .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 }, 276 { .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 }, 277 { .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 }, 278 { .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 }, 279 { .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 }, 280 { .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 }, 281 { .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, 282 .block_w = { 16, 8, 0, 0 }, .block_h = { 32, 16, 0, 0 }}, 283 { .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, 284 .block_w = { 16, 8, 0, 0 }, .block_h = { 32, 16, 0, 0 }}, 285 286 /* YUV planar formats */ 287 { .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 }, 288 { .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 }, 289 { .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 }, 290 { .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 }, 291 { .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 }, 292 { .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 }, 293 { .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 }, 294 { .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 }, 295 { .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 }, 296 { .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 }, 297 298 { .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 }, 299 { .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 }, 300 { .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 }, 301 { .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 }, 302 { .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 }, 303 { .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 }, 304 { .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 }, 305 306 /* Tiled YUV formats */ 307 { .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 }, 308 { .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, 309 .block_w = { 4, 2, 0, 0 }, .block_h = { 1, 1, 0, 0 }}, 310 { .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 }, 311 312 /* YUV planar formats, non contiguous variant */ 313 { .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 }, 314 { .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 }, 315 { .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 }, 316 { .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 }, 317 { .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 }, 318 { .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 }, 319 320 { .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 }, 321 { .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 }, 322 { .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 }, 323 { .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 }, 324 { .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 }, 325 326 /* Bayer RGB formats */ 327 { .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 }, 328 { .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 }, 329 { .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 }, 330 { .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 }, 331 { .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 }, 332 { .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 }, 333 { .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 }, 334 { .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 }, 335 { .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 }, 336 { .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 }, 337 { .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 }, 338 { .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 }, 339 { .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 }, 340 { .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 }, 341 { .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 }, 342 { .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 }, 343 { .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 }, 344 { .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 }, 345 { .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 }, 346 { .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 }, 347 }; 348 unsigned int i; 349 350 for (i = 0; i < ARRAY_SIZE(formats); ++i) 351 if (formats[i].format == format) 352 return &formats[i]; 353 return NULL; 354 } 355 EXPORT_SYMBOL(v4l2_format_info); 356 357 static inline unsigned int v4l2_format_block_width(const struct v4l2_format_info *info, int plane) 358 { 359 if (!info->block_w[plane]) 360 return 1; 361 return info->block_w[plane]; 362 } 363 364 static inline unsigned int v4l2_format_block_height(const struct v4l2_format_info *info, int plane) 365 { 366 if (!info->block_h[plane]) 367 return 1; 368 return info->block_h[plane]; 369 } 370 371 static inline unsigned int v4l2_format_plane_stride(const struct v4l2_format_info *info, int plane, 372 unsigned int width) 373 { 374 unsigned int hdiv = plane ? info->hdiv : 1; 375 unsigned int aligned_width = 376 ALIGN(width, v4l2_format_block_width(info, plane)); 377 378 return DIV_ROUND_UP(aligned_width, hdiv) * 379 info->bpp[plane] / info->bpp_div[plane]; 380 } 381 382 static inline unsigned int v4l2_format_plane_height(const struct v4l2_format_info *info, int plane, 383 unsigned int height) 384 { 385 unsigned int vdiv = plane ? info->vdiv : 1; 386 unsigned int aligned_height = 387 ALIGN(height, v4l2_format_block_height(info, plane)); 388 389 return DIV_ROUND_UP(aligned_height, vdiv); 390 } 391 392 static inline unsigned int v4l2_format_plane_size(const struct v4l2_format_info *info, int plane, 393 unsigned int width, unsigned int height) 394 { 395 return v4l2_format_plane_stride(info, plane, width) * 396 v4l2_format_plane_height(info, plane, height); 397 } 398 399 void v4l2_apply_frmsize_constraints(u32 *width, u32 *height, 400 const struct v4l2_frmsize_stepwise *frmsize) 401 { 402 if (!frmsize) 403 return; 404 405 /* 406 * Clamp width/height to meet min/max constraints and round it up to 407 * macroblock alignment. 408 */ 409 *width = clamp_roundup(*width, frmsize->min_width, frmsize->max_width, 410 frmsize->step_width); 411 *height = clamp_roundup(*height, frmsize->min_height, frmsize->max_height, 412 frmsize->step_height); 413 } 414 EXPORT_SYMBOL_GPL(v4l2_apply_frmsize_constraints); 415 416 int v4l2_fill_pixfmt_mp(struct v4l2_pix_format_mplane *pixfmt, 417 u32 pixelformat, u32 width, u32 height) 418 { 419 const struct v4l2_format_info *info; 420 struct v4l2_plane_pix_format *plane; 421 int i; 422 423 info = v4l2_format_info(pixelformat); 424 if (!info) 425 return -EINVAL; 426 427 pixfmt->width = width; 428 pixfmt->height = height; 429 pixfmt->pixelformat = pixelformat; 430 pixfmt->num_planes = info->mem_planes; 431 432 if (info->mem_planes == 1) { 433 plane = &pixfmt->plane_fmt[0]; 434 plane->bytesperline = v4l2_format_plane_stride(info, 0, width); 435 plane->sizeimage = 0; 436 437 for (i = 0; i < info->comp_planes; i++) 438 plane->sizeimage += 439 v4l2_format_plane_size(info, i, width, height); 440 } else { 441 for (i = 0; i < info->comp_planes; i++) { 442 plane = &pixfmt->plane_fmt[i]; 443 plane->bytesperline = 444 v4l2_format_plane_stride(info, i, width); 445 plane->sizeimage = plane->bytesperline * 446 v4l2_format_plane_height(info, i, height); 447 } 448 } 449 return 0; 450 } 451 EXPORT_SYMBOL_GPL(v4l2_fill_pixfmt_mp); 452 453 int v4l2_fill_pixfmt(struct v4l2_pix_format *pixfmt, u32 pixelformat, 454 u32 width, u32 height) 455 { 456 const struct v4l2_format_info *info; 457 int i; 458 459 info = v4l2_format_info(pixelformat); 460 if (!info) 461 return -EINVAL; 462 463 /* Single planar API cannot be used for multi plane formats. */ 464 if (info->mem_planes > 1) 465 return -EINVAL; 466 467 pixfmt->width = width; 468 pixfmt->height = height; 469 pixfmt->pixelformat = pixelformat; 470 pixfmt->bytesperline = v4l2_format_plane_stride(info, 0, width); 471 pixfmt->sizeimage = 0; 472 473 for (i = 0; i < info->comp_planes; i++) 474 pixfmt->sizeimage += 475 v4l2_format_plane_size(info, i, width, height); 476 return 0; 477 } 478 EXPORT_SYMBOL_GPL(v4l2_fill_pixfmt); 479 480 s64 __v4l2_get_link_freq_ctrl(struct v4l2_ctrl_handler *handler, 481 unsigned int mul, unsigned int div) 482 { 483 struct v4l2_ctrl *ctrl; 484 s64 freq; 485 486 ctrl = v4l2_ctrl_find(handler, V4L2_CID_LINK_FREQ); 487 if (ctrl) { 488 struct v4l2_querymenu qm = { .id = V4L2_CID_LINK_FREQ }; 489 int ret; 490 491 qm.index = v4l2_ctrl_g_ctrl(ctrl); 492 493 ret = v4l2_querymenu(handler, &qm); 494 if (ret) 495 return -ENOENT; 496 497 freq = qm.value; 498 } else { 499 if (!mul || !div) 500 return -ENOENT; 501 502 ctrl = v4l2_ctrl_find(handler, V4L2_CID_PIXEL_RATE); 503 if (!ctrl) 504 return -ENOENT; 505 506 freq = div_u64(v4l2_ctrl_g_ctrl_int64(ctrl) * mul, div); 507 508 pr_warn("%s: Link frequency estimated using pixel rate: result might be inaccurate\n", 509 __func__); 510 pr_warn("%s: Consider implementing support for V4L2_CID_LINK_FREQ in the transmitter driver\n", 511 __func__); 512 } 513 514 return freq > 0 ? freq : -EINVAL; 515 } 516 EXPORT_SYMBOL_GPL(__v4l2_get_link_freq_ctrl); 517 518 #ifdef CONFIG_MEDIA_CONTROLLER 519 s64 __v4l2_get_link_freq_pad(struct media_pad *pad, unsigned int mul, 520 unsigned int div) 521 { 522 struct v4l2_mbus_config mbus_config = {}; 523 struct v4l2_subdev *sd; 524 int ret; 525 526 sd = media_entity_to_v4l2_subdev(pad->entity); 527 ret = v4l2_subdev_call(sd, pad, get_mbus_config, pad->index, 528 &mbus_config); 529 if (ret < 0 && ret != -ENOIOCTLCMD) 530 return ret; 531 532 if (mbus_config.link_freq) 533 return mbus_config.link_freq; 534 535 /* 536 * Fall back to using the link frequency control if the media bus config 537 * doesn't provide a link frequency. 538 */ 539 return __v4l2_get_link_freq_ctrl(sd->ctrl_handler, mul, div); 540 } 541 EXPORT_SYMBOL_GPL(__v4l2_get_link_freq_pad); 542 #endif /* CONFIG_MEDIA_CONTROLLER */ 543 544 /* 545 * Simplify a fraction using a simple continued fraction decomposition. The 546 * idea here is to convert fractions such as 333333/10000000 to 1/30 using 547 * 32 bit arithmetic only. The algorithm is not perfect and relies upon two 548 * arbitrary parameters to remove non-significative terms from the simple 549 * continued fraction decomposition. Using 8 and 333 for n_terms and threshold 550 * respectively seems to give nice results. 551 */ 552 void v4l2_simplify_fraction(u32 *numerator, u32 *denominator, 553 unsigned int n_terms, unsigned int threshold) 554 { 555 u32 *an; 556 u32 x, y, r; 557 unsigned int i, n; 558 559 an = kmalloc_array(n_terms, sizeof(*an), GFP_KERNEL); 560 if (an == NULL) 561 return; 562 563 /* 564 * Convert the fraction to a simple continued fraction. See 565 * https://en.wikipedia.org/wiki/Continued_fraction 566 * Stop if the current term is bigger than or equal to the given 567 * threshold. 568 */ 569 x = *numerator; 570 y = *denominator; 571 572 for (n = 0; n < n_terms && y != 0; ++n) { 573 an[n] = x / y; 574 if (an[n] >= threshold) { 575 if (n < 2) 576 n++; 577 break; 578 } 579 580 r = x - an[n] * y; 581 x = y; 582 y = r; 583 } 584 585 /* Expand the simple continued fraction back to an integer fraction. */ 586 x = 0; 587 y = 1; 588 589 for (i = n; i > 0; --i) { 590 r = y; 591 y = an[i-1] * y + x; 592 x = r; 593 } 594 595 *numerator = y; 596 *denominator = x; 597 kfree(an); 598 } 599 EXPORT_SYMBOL_GPL(v4l2_simplify_fraction); 600 601 /* 602 * Convert a fraction to a frame interval in 100ns multiples. The idea here is 603 * to compute numerator / denominator * 10000000 using 32 bit fixed point 604 * arithmetic only. 605 */ 606 u32 v4l2_fraction_to_interval(u32 numerator, u32 denominator) 607 { 608 u32 multiplier; 609 610 /* Saturate the result if the operation would overflow. */ 611 if (denominator == 0 || 612 numerator/denominator >= ((u32)-1)/10000000) 613 return (u32)-1; 614 615 /* 616 * Divide both the denominator and the multiplier by two until 617 * numerator * multiplier doesn't overflow. If anyone knows a better 618 * algorithm please let me know. 619 */ 620 multiplier = 10000000; 621 while (numerator > ((u32)-1)/multiplier) { 622 multiplier /= 2; 623 denominator /= 2; 624 } 625 626 return denominator ? numerator * multiplier / denominator : 0; 627 } 628 EXPORT_SYMBOL_GPL(v4l2_fraction_to_interval); 629 630 int v4l2_link_freq_to_bitmap(struct device *dev, const u64 *fw_link_freqs, 631 unsigned int num_of_fw_link_freqs, 632 const s64 *driver_link_freqs, 633 unsigned int num_of_driver_link_freqs, 634 unsigned long *bitmap) 635 { 636 unsigned int i; 637 638 *bitmap = 0; 639 640 if (!num_of_fw_link_freqs) { 641 dev_err(dev, "no link frequencies in firmware\n"); 642 return -ENODATA; 643 } 644 645 for (i = 0; i < num_of_fw_link_freqs; i++) { 646 unsigned int j; 647 648 for (j = 0; j < num_of_driver_link_freqs; j++) { 649 if (fw_link_freqs[i] != driver_link_freqs[j]) 650 continue; 651 652 dev_dbg(dev, "enabling link frequency %lld Hz\n", 653 driver_link_freqs[j]); 654 *bitmap |= BIT(j); 655 break; 656 } 657 } 658 659 if (!*bitmap) { 660 dev_err(dev, "no matching link frequencies found\n"); 661 662 dev_dbg(dev, "specified in firmware:\n"); 663 for (i = 0; i < num_of_fw_link_freqs; i++) 664 dev_dbg(dev, "\t%llu Hz\n", fw_link_freqs[i]); 665 666 dev_dbg(dev, "driver supported:\n"); 667 for (i = 0; i < num_of_driver_link_freqs; i++) 668 dev_dbg(dev, "\t%lld Hz\n", driver_link_freqs[i]); 669 670 return -ENOENT; 671 } 672 673 return 0; 674 } 675 EXPORT_SYMBOL_GPL(v4l2_link_freq_to_bitmap); 676