0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 #include <linux/module.h>
0038 #include <linux/types.h>
0039 #include <linux/kernel.h>
0040 #include <linux/mm.h>
0041 #include <linux/string.h>
0042 #include <linux/errno.h>
0043 #include <linux/uaccess.h>
0044 #include <asm/io.h>
0045 #include <asm/div64.h>
0046 #include <media/v4l2-common.h>
0047 #include <media/v4l2-device.h>
0048 #include <media/v4l2-ctrls.h>
0049
0050 #include <linux/videodev2.h>
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065 int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 _min, s32 _max, s32 _step, s32 _def)
0066 {
0067 const char *name;
0068 s64 min = _min;
0069 s64 max = _max;
0070 u64 step = _step;
0071 s64 def = _def;
0072
0073 v4l2_ctrl_fill(qctrl->id, &name, &qctrl->type,
0074 &min, &max, &step, &def, &qctrl->flags);
0075
0076 if (name == NULL)
0077 return -EINVAL;
0078
0079 qctrl->minimum = min;
0080 qctrl->maximum = max;
0081 qctrl->step = step;
0082 qctrl->default_value = def;
0083 qctrl->reserved[0] = qctrl->reserved[1] = 0;
0084 strscpy(qctrl->name, name, sizeof(qctrl->name));
0085 return 0;
0086 }
0087 EXPORT_SYMBOL(v4l2_ctrl_query_fill);
0088
0089
0090
0091
0092
0093 static unsigned int clamp_align(unsigned int x, unsigned int min,
0094 unsigned int max, unsigned int align)
0095 {
0096
0097 unsigned int mask = ~((1 << align) - 1);
0098
0099
0100 x = clamp(x, (min + ~mask) & mask, max & mask);
0101
0102
0103 if (align)
0104 x = (x + (1 << (align - 1))) & mask;
0105
0106 return x;
0107 }
0108
0109 static unsigned int clamp_roundup(unsigned int x, unsigned int min,
0110 unsigned int max, unsigned int alignment)
0111 {
0112 x = clamp(x, min, max);
0113 if (alignment)
0114 x = round_up(x, alignment);
0115
0116 return x;
0117 }
0118
0119 void v4l_bound_align_image(u32 *w, unsigned int wmin, unsigned int wmax,
0120 unsigned int walign,
0121 u32 *h, unsigned int hmin, unsigned int hmax,
0122 unsigned int halign, unsigned int salign)
0123 {
0124 *w = clamp_align(*w, wmin, wmax, walign);
0125 *h = clamp_align(*h, hmin, hmax, halign);
0126
0127
0128 if (!salign)
0129 return;
0130
0131
0132 walign = __ffs(*w);
0133 halign = __ffs(*h);
0134
0135 if (walign + halign < salign) {
0136
0137 unsigned int wmaxa = __fls(wmax ^ (wmin - 1));
0138
0139 unsigned int hmaxa = __fls(hmax ^ (hmin - 1));
0140
0141
0142 do {
0143 if (halign >= hmaxa ||
0144 (walign <= halign && walign < wmaxa)) {
0145 *w = clamp_align(*w, wmin, wmax, walign + 1);
0146 walign = __ffs(*w);
0147 } else {
0148 *h = clamp_align(*h, hmin, hmax, halign + 1);
0149 halign = __ffs(*h);
0150 }
0151 } while (halign + walign < salign);
0152 }
0153 }
0154 EXPORT_SYMBOL_GPL(v4l_bound_align_image);
0155
0156 const void *
0157 __v4l2_find_nearest_size(const void *array, size_t array_size,
0158 size_t entry_size, size_t width_offset,
0159 size_t height_offset, s32 width, s32 height)
0160 {
0161 u32 error, min_error = U32_MAX;
0162 const void *best = NULL;
0163 unsigned int i;
0164
0165 if (!array)
0166 return NULL;
0167
0168 for (i = 0; i < array_size; i++, array += entry_size) {
0169 const u32 *entry_width = array + width_offset;
0170 const u32 *entry_height = array + height_offset;
0171
0172 error = abs(*entry_width - width) + abs(*entry_height - height);
0173 if (error > min_error)
0174 continue;
0175
0176 min_error = error;
0177 best = array;
0178 if (!error)
0179 break;
0180 }
0181
0182 return best;
0183 }
0184 EXPORT_SYMBOL_GPL(__v4l2_find_nearest_size);
0185
0186 int v4l2_g_parm_cap(struct video_device *vdev,
0187 struct v4l2_subdev *sd, struct v4l2_streamparm *a)
0188 {
0189 struct v4l2_subdev_frame_interval ival = { 0 };
0190 int ret;
0191
0192 if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
0193 a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
0194 return -EINVAL;
0195
0196 if (vdev->device_caps & V4L2_CAP_READWRITE)
0197 a->parm.capture.readbuffers = 2;
0198 if (v4l2_subdev_has_op(sd, video, g_frame_interval))
0199 a->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
0200 ret = v4l2_subdev_call(sd, video, g_frame_interval, &ival);
0201 if (!ret)
0202 a->parm.capture.timeperframe = ival.interval;
0203 return ret;
0204 }
0205 EXPORT_SYMBOL_GPL(v4l2_g_parm_cap);
0206
0207 int v4l2_s_parm_cap(struct video_device *vdev,
0208 struct v4l2_subdev *sd, struct v4l2_streamparm *a)
0209 {
0210 struct v4l2_subdev_frame_interval ival = {
0211 .interval = a->parm.capture.timeperframe
0212 };
0213 int ret;
0214
0215 if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
0216 a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
0217 return -EINVAL;
0218
0219 memset(&a->parm, 0, sizeof(a->parm));
0220 if (vdev->device_caps & V4L2_CAP_READWRITE)
0221 a->parm.capture.readbuffers = 2;
0222 else
0223 a->parm.capture.readbuffers = 0;
0224
0225 if (v4l2_subdev_has_op(sd, video, g_frame_interval))
0226 a->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
0227 ret = v4l2_subdev_call(sd, video, s_frame_interval, &ival);
0228 if (!ret)
0229 a->parm.capture.timeperframe = ival.interval;
0230 return ret;
0231 }
0232 EXPORT_SYMBOL_GPL(v4l2_s_parm_cap);
0233
0234 const struct v4l2_format_info *v4l2_format_info(u32 format)
0235 {
0236 static const struct v4l2_format_info formats[] = {
0237
0238 { .format = V4L2_PIX_FMT_BGR24, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0239 { .format = V4L2_PIX_FMT_RGB24, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0240 { .format = V4L2_PIX_FMT_HSV24, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0241 { .format = V4L2_PIX_FMT_BGR32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0242 { .format = V4L2_PIX_FMT_XBGR32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0243 { .format = V4L2_PIX_FMT_BGRX32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0244 { .format = V4L2_PIX_FMT_RGB32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0245 { .format = V4L2_PIX_FMT_XRGB32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0246 { .format = V4L2_PIX_FMT_RGBX32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0247 { .format = V4L2_PIX_FMT_HSV32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0248 { .format = V4L2_PIX_FMT_ARGB32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0249 { .format = V4L2_PIX_FMT_RGBA32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0250 { .format = V4L2_PIX_FMT_ABGR32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0251 { .format = V4L2_PIX_FMT_BGRA32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0252 { .format = V4L2_PIX_FMT_RGB565, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0253 { .format = V4L2_PIX_FMT_RGB555, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0254 { .format = V4L2_PIX_FMT_BGR666, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0255
0256
0257 { .format = V4L2_PIX_FMT_YUYV, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 },
0258 { .format = V4L2_PIX_FMT_YVYU, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 },
0259 { .format = V4L2_PIX_FMT_UYVY, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 },
0260 { .format = V4L2_PIX_FMT_VYUY, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 },
0261
0262
0263 { .format = V4L2_PIX_FMT_NV12, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 },
0264 { .format = V4L2_PIX_FMT_NV21, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 },
0265 { .format = V4L2_PIX_FMT_NV16, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 },
0266 { .format = V4L2_PIX_FMT_NV61, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 },
0267 { .format = V4L2_PIX_FMT_NV24, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0268 { .format = V4L2_PIX_FMT_NV42, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0269 { .format = V4L2_PIX_FMT_P010, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 2, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 },
0270
0271 { .format = V4L2_PIX_FMT_YUV410, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 4 },
0272 { .format = V4L2_PIX_FMT_YVU410, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 4 },
0273 { .format = V4L2_PIX_FMT_YUV411P, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 1 },
0274 { .format = V4L2_PIX_FMT_YUV420, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 2 },
0275 { .format = V4L2_PIX_FMT_YVU420, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 2 },
0276 { .format = V4L2_PIX_FMT_YUV422P, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 1 },
0277 { .format = V4L2_PIX_FMT_GREY, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0278
0279
0280 { .format = V4L2_PIX_FMT_NV12_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 },
0281 { .format = V4L2_PIX_FMT_P010_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 2, 4, 0, 0 }, .hdiv = 2, .vdiv = 2 },
0282
0283
0284 { .format = V4L2_PIX_FMT_YUV420M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 2 },
0285 { .format = V4L2_PIX_FMT_YVU420M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 2 },
0286 { .format = V4L2_PIX_FMT_YUV422M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 1 },
0287 { .format = V4L2_PIX_FMT_YVU422M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 1 },
0288 { .format = V4L2_PIX_FMT_YUV444M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 1, .vdiv = 1 },
0289 { .format = V4L2_PIX_FMT_YVU444M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 1, .vdiv = 1 },
0290
0291 { .format = V4L2_PIX_FMT_NV12M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 },
0292 { .format = V4L2_PIX_FMT_NV21M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 },
0293 { .format = V4L2_PIX_FMT_NV16M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 },
0294 { .format = V4L2_PIX_FMT_NV61M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 },
0295
0296
0297 { .format = V4L2_PIX_FMT_SBGGR8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0298 { .format = V4L2_PIX_FMT_SGBRG8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0299 { .format = V4L2_PIX_FMT_SGRBG8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0300 { .format = V4L2_PIX_FMT_SRGGB8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0301 { .format = V4L2_PIX_FMT_SBGGR10, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0302 { .format = V4L2_PIX_FMT_SGBRG10, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0303 { .format = V4L2_PIX_FMT_SGRBG10, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0304 { .format = V4L2_PIX_FMT_SRGGB10, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0305 { .format = V4L2_PIX_FMT_SBGGR10ALAW8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0306 { .format = V4L2_PIX_FMT_SGBRG10ALAW8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0307 { .format = V4L2_PIX_FMT_SGRBG10ALAW8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0308 { .format = V4L2_PIX_FMT_SRGGB10ALAW8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0309 { .format = V4L2_PIX_FMT_SBGGR10DPCM8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0310 { .format = V4L2_PIX_FMT_SGBRG10DPCM8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0311 { .format = V4L2_PIX_FMT_SGRBG10DPCM8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0312 { .format = V4L2_PIX_FMT_SRGGB10DPCM8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0313 { .format = V4L2_PIX_FMT_SBGGR12, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0314 { .format = V4L2_PIX_FMT_SGBRG12, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0315 { .format = V4L2_PIX_FMT_SGRBG12, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0316 { .format = V4L2_PIX_FMT_SRGGB12, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
0317 };
0318 unsigned int i;
0319
0320 for (i = 0; i < ARRAY_SIZE(formats); ++i)
0321 if (formats[i].format == format)
0322 return &formats[i];
0323 return NULL;
0324 }
0325 EXPORT_SYMBOL(v4l2_format_info);
0326
0327 static inline unsigned int v4l2_format_block_width(const struct v4l2_format_info *info, int plane)
0328 {
0329 if (!info->block_w[plane])
0330 return 1;
0331 return info->block_w[plane];
0332 }
0333
0334 static inline unsigned int v4l2_format_block_height(const struct v4l2_format_info *info, int plane)
0335 {
0336 if (!info->block_h[plane])
0337 return 1;
0338 return info->block_h[plane];
0339 }
0340
0341 void v4l2_apply_frmsize_constraints(u32 *width, u32 *height,
0342 const struct v4l2_frmsize_stepwise *frmsize)
0343 {
0344 if (!frmsize)
0345 return;
0346
0347
0348
0349
0350
0351 *width = clamp_roundup(*width, frmsize->min_width, frmsize->max_width,
0352 frmsize->step_width);
0353 *height = clamp_roundup(*height, frmsize->min_height, frmsize->max_height,
0354 frmsize->step_height);
0355 }
0356 EXPORT_SYMBOL_GPL(v4l2_apply_frmsize_constraints);
0357
0358 int v4l2_fill_pixfmt_mp(struct v4l2_pix_format_mplane *pixfmt,
0359 u32 pixelformat, u32 width, u32 height)
0360 {
0361 const struct v4l2_format_info *info;
0362 struct v4l2_plane_pix_format *plane;
0363 int i;
0364
0365 info = v4l2_format_info(pixelformat);
0366 if (!info)
0367 return -EINVAL;
0368
0369 pixfmt->width = width;
0370 pixfmt->height = height;
0371 pixfmt->pixelformat = pixelformat;
0372 pixfmt->num_planes = info->mem_planes;
0373
0374 if (info->mem_planes == 1) {
0375 plane = &pixfmt->plane_fmt[0];
0376 plane->bytesperline = ALIGN(width, v4l2_format_block_width(info, 0)) * info->bpp[0];
0377 plane->sizeimage = 0;
0378
0379 for (i = 0; i < info->comp_planes; i++) {
0380 unsigned int hdiv = (i == 0) ? 1 : info->hdiv;
0381 unsigned int vdiv = (i == 0) ? 1 : info->vdiv;
0382 unsigned int aligned_width;
0383 unsigned int aligned_height;
0384
0385 aligned_width = ALIGN(width, v4l2_format_block_width(info, i));
0386 aligned_height = ALIGN(height, v4l2_format_block_height(info, i));
0387
0388 plane->sizeimage += info->bpp[i] *
0389 DIV_ROUND_UP(aligned_width, hdiv) *
0390 DIV_ROUND_UP(aligned_height, vdiv);
0391 }
0392 } else {
0393 for (i = 0; i < info->comp_planes; i++) {
0394 unsigned int hdiv = (i == 0) ? 1 : info->hdiv;
0395 unsigned int vdiv = (i == 0) ? 1 : info->vdiv;
0396 unsigned int aligned_width;
0397 unsigned int aligned_height;
0398
0399 aligned_width = ALIGN(width, v4l2_format_block_width(info, i));
0400 aligned_height = ALIGN(height, v4l2_format_block_height(info, i));
0401
0402 plane = &pixfmt->plane_fmt[i];
0403 plane->bytesperline =
0404 info->bpp[i] * DIV_ROUND_UP(aligned_width, hdiv);
0405 plane->sizeimage =
0406 plane->bytesperline * DIV_ROUND_UP(aligned_height, vdiv);
0407 }
0408 }
0409 return 0;
0410 }
0411 EXPORT_SYMBOL_GPL(v4l2_fill_pixfmt_mp);
0412
0413 int v4l2_fill_pixfmt(struct v4l2_pix_format *pixfmt, u32 pixelformat,
0414 u32 width, u32 height)
0415 {
0416 const struct v4l2_format_info *info;
0417 int i;
0418
0419 info = v4l2_format_info(pixelformat);
0420 if (!info)
0421 return -EINVAL;
0422
0423
0424 if (info->mem_planes > 1)
0425 return -EINVAL;
0426
0427 pixfmt->width = width;
0428 pixfmt->height = height;
0429 pixfmt->pixelformat = pixelformat;
0430 pixfmt->bytesperline = ALIGN(width, v4l2_format_block_width(info, 0)) * info->bpp[0];
0431 pixfmt->sizeimage = 0;
0432
0433 for (i = 0; i < info->comp_planes; i++) {
0434 unsigned int hdiv = (i == 0) ? 1 : info->hdiv;
0435 unsigned int vdiv = (i == 0) ? 1 : info->vdiv;
0436 unsigned int aligned_width;
0437 unsigned int aligned_height;
0438
0439 aligned_width = ALIGN(width, v4l2_format_block_width(info, i));
0440 aligned_height = ALIGN(height, v4l2_format_block_height(info, i));
0441
0442 pixfmt->sizeimage += info->bpp[i] *
0443 DIV_ROUND_UP(aligned_width, hdiv) *
0444 DIV_ROUND_UP(aligned_height, vdiv);
0445 }
0446 return 0;
0447 }
0448 EXPORT_SYMBOL_GPL(v4l2_fill_pixfmt);
0449
0450 s64 v4l2_get_link_freq(struct v4l2_ctrl_handler *handler, unsigned int mul,
0451 unsigned int div)
0452 {
0453 struct v4l2_ctrl *ctrl;
0454 s64 freq;
0455
0456 ctrl = v4l2_ctrl_find(handler, V4L2_CID_LINK_FREQ);
0457 if (ctrl) {
0458 struct v4l2_querymenu qm = { .id = V4L2_CID_LINK_FREQ };
0459 int ret;
0460
0461 qm.index = v4l2_ctrl_g_ctrl(ctrl);
0462
0463 ret = v4l2_querymenu(handler, &qm);
0464 if (ret)
0465 return -ENOENT;
0466
0467 freq = qm.value;
0468 } else {
0469 if (!mul || !div)
0470 return -ENOENT;
0471
0472 ctrl = v4l2_ctrl_find(handler, V4L2_CID_PIXEL_RATE);
0473 if (!ctrl)
0474 return -ENOENT;
0475
0476 freq = div_u64(v4l2_ctrl_g_ctrl_int64(ctrl) * mul, div);
0477
0478 pr_warn("%s: Link frequency estimated using pixel rate: result might be inaccurate\n",
0479 __func__);
0480 pr_warn("%s: Consider implementing support for V4L2_CID_LINK_FREQ in the transmitter driver\n",
0481 __func__);
0482 }
0483
0484 return freq > 0 ? freq : -EINVAL;
0485 }
0486 EXPORT_SYMBOL_GPL(v4l2_get_link_freq);