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/i2c.h> 44 #if defined(CONFIG_SPI) 45 #include <linux/spi/spi.h> 46 #endif 47 #include <linux/uaccess.h> 48 #include <asm/pgtable.h> 49 #include <asm/io.h> 50 #include <asm/div64.h> 51 #include <media/v4l2-common.h> 52 #include <media/v4l2-device.h> 53 #include <media/v4l2-ctrls.h> 54 55 #include <linux/videodev2.h> 56 57 MODULE_AUTHOR("Bill Dirks, Justin Schoeman, Gerd Knorr"); 58 MODULE_DESCRIPTION("misc helper functions for v4l2 device drivers"); 59 MODULE_LICENSE("GPL"); 60 61 /* 62 * 63 * V 4 L 2 D R I V E R H E L P E R A P I 64 * 65 */ 66 67 /* 68 * Video Standard Operations (contributed by Michael Schimek) 69 */ 70 71 /* Helper functions for control handling */ 72 73 /* Fill in a struct v4l2_queryctrl */ 74 int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 _min, s32 _max, s32 _step, s32 _def) 75 { 76 const char *name; 77 s64 min = _min; 78 s64 max = _max; 79 u64 step = _step; 80 s64 def = _def; 81 82 v4l2_ctrl_fill(qctrl->id, &name, &qctrl->type, 83 &min, &max, &step, &def, &qctrl->flags); 84 85 if (name == NULL) 86 return -EINVAL; 87 88 qctrl->minimum = min; 89 qctrl->maximum = max; 90 qctrl->step = step; 91 qctrl->default_value = def; 92 qctrl->reserved[0] = qctrl->reserved[1] = 0; 93 strscpy(qctrl->name, name, sizeof(qctrl->name)); 94 return 0; 95 } 96 EXPORT_SYMBOL(v4l2_ctrl_query_fill); 97 98 /* I2C Helper functions */ 99 100 #if IS_ENABLED(CONFIG_I2C) 101 102 void v4l2_i2c_subdev_set_name(struct v4l2_subdev *sd, struct i2c_client *client, 103 const char *devname, const char *postfix) 104 { 105 if (!devname) 106 devname = client->dev.driver->name; 107 if (!postfix) 108 postfix = ""; 109 110 snprintf(sd->name, sizeof(sd->name), "%s%s %d-%04x", devname, postfix, 111 i2c_adapter_id(client->adapter), client->addr); 112 } 113 EXPORT_SYMBOL_GPL(v4l2_i2c_subdev_set_name); 114 115 void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client, 116 const struct v4l2_subdev_ops *ops) 117 { 118 v4l2_subdev_init(sd, ops); 119 sd->flags |= V4L2_SUBDEV_FL_IS_I2C; 120 /* the owner is the same as the i2c_client's driver owner */ 121 sd->owner = client->dev.driver->owner; 122 sd->dev = &client->dev; 123 /* i2c_client and v4l2_subdev point to one another */ 124 v4l2_set_subdevdata(sd, client); 125 i2c_set_clientdata(client, sd); 126 v4l2_i2c_subdev_set_name(sd, client, NULL, NULL); 127 } 128 EXPORT_SYMBOL_GPL(v4l2_i2c_subdev_init); 129 130 /* Load an i2c sub-device. */ 131 struct v4l2_subdev *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev, 132 struct i2c_adapter *adapter, struct i2c_board_info *info, 133 const unsigned short *probe_addrs) 134 { 135 struct v4l2_subdev *sd = NULL; 136 struct i2c_client *client; 137 138 BUG_ON(!v4l2_dev); 139 140 request_module(I2C_MODULE_PREFIX "%s", info->type); 141 142 /* Create the i2c client */ 143 if (info->addr == 0 && probe_addrs) 144 client = i2c_new_probed_device(adapter, info, probe_addrs, 145 NULL); 146 else 147 client = i2c_new_device(adapter, info); 148 149 /* Note: by loading the module first we are certain that c->driver 150 will be set if the driver was found. If the module was not loaded 151 first, then the i2c core tries to delay-load the module for us, 152 and then c->driver is still NULL until the module is finally 153 loaded. This delay-load mechanism doesn't work if other drivers 154 want to use the i2c device, so explicitly loading the module 155 is the best alternative. */ 156 if (client == NULL || client->dev.driver == NULL) 157 goto error; 158 159 /* Lock the module so we can safely get the v4l2_subdev pointer */ 160 if (!try_module_get(client->dev.driver->owner)) 161 goto error; 162 sd = i2c_get_clientdata(client); 163 164 /* Register with the v4l2_device which increases the module's 165 use count as well. */ 166 if (v4l2_device_register_subdev(v4l2_dev, sd)) 167 sd = NULL; 168 /* Decrease the module use count to match the first try_module_get. */ 169 module_put(client->dev.driver->owner); 170 171 error: 172 /* If we have a client but no subdev, then something went wrong and 173 we must unregister the client. */ 174 if (client && sd == NULL) 175 i2c_unregister_device(client); 176 return sd; 177 } 178 EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev_board); 179 180 struct v4l2_subdev *v4l2_i2c_new_subdev(struct v4l2_device *v4l2_dev, 181 struct i2c_adapter *adapter, const char *client_type, 182 u8 addr, const unsigned short *probe_addrs) 183 { 184 struct i2c_board_info info; 185 186 /* Setup the i2c board info with the device type and 187 the device address. */ 188 memset(&info, 0, sizeof(info)); 189 strscpy(info.type, client_type, sizeof(info.type)); 190 info.addr = addr; 191 192 return v4l2_i2c_new_subdev_board(v4l2_dev, adapter, &info, probe_addrs); 193 } 194 EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev); 195 196 /* Return i2c client address of v4l2_subdev. */ 197 unsigned short v4l2_i2c_subdev_addr(struct v4l2_subdev *sd) 198 { 199 struct i2c_client *client = v4l2_get_subdevdata(sd); 200 201 return client ? client->addr : I2C_CLIENT_END; 202 } 203 EXPORT_SYMBOL_GPL(v4l2_i2c_subdev_addr); 204 205 /* Return a list of I2C tuner addresses to probe. Use only if the tuner 206 addresses are unknown. */ 207 const unsigned short *v4l2_i2c_tuner_addrs(enum v4l2_i2c_tuner_type type) 208 { 209 static const unsigned short radio_addrs[] = { 210 #if IS_ENABLED(CONFIG_MEDIA_TUNER_TEA5761) 211 0x10, 212 #endif 213 0x60, 214 I2C_CLIENT_END 215 }; 216 static const unsigned short demod_addrs[] = { 217 0x42, 0x43, 0x4a, 0x4b, 218 I2C_CLIENT_END 219 }; 220 static const unsigned short tv_addrs[] = { 221 0x42, 0x43, 0x4a, 0x4b, /* tda8290 */ 222 0x60, 0x61, 0x62, 0x63, 0x64, 223 I2C_CLIENT_END 224 }; 225 226 switch (type) { 227 case ADDRS_RADIO: 228 return radio_addrs; 229 case ADDRS_DEMOD: 230 return demod_addrs; 231 case ADDRS_TV: 232 return tv_addrs; 233 case ADDRS_TV_WITH_DEMOD: 234 return tv_addrs + 4; 235 } 236 return NULL; 237 } 238 EXPORT_SYMBOL_GPL(v4l2_i2c_tuner_addrs); 239 240 #endif /* defined(CONFIG_I2C) */ 241 242 #if defined(CONFIG_SPI) 243 244 /* Load an spi sub-device. */ 245 246 void v4l2_spi_subdev_init(struct v4l2_subdev *sd, struct spi_device *spi, 247 const struct v4l2_subdev_ops *ops) 248 { 249 v4l2_subdev_init(sd, ops); 250 sd->flags |= V4L2_SUBDEV_FL_IS_SPI; 251 /* the owner is the same as the spi_device's driver owner */ 252 sd->owner = spi->dev.driver->owner; 253 sd->dev = &spi->dev; 254 /* spi_device and v4l2_subdev point to one another */ 255 v4l2_set_subdevdata(sd, spi); 256 spi_set_drvdata(spi, sd); 257 /* initialize name */ 258 snprintf(sd->name, sizeof(sd->name), "%s %s", 259 spi->dev.driver->name, dev_name(&spi->dev)); 260 } 261 EXPORT_SYMBOL_GPL(v4l2_spi_subdev_init); 262 263 struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev, 264 struct spi_master *master, struct spi_board_info *info) 265 { 266 struct v4l2_subdev *sd = NULL; 267 struct spi_device *spi = NULL; 268 269 BUG_ON(!v4l2_dev); 270 271 if (info->modalias[0]) 272 request_module(info->modalias); 273 274 spi = spi_new_device(master, info); 275 276 if (spi == NULL || spi->dev.driver == NULL) 277 goto error; 278 279 if (!try_module_get(spi->dev.driver->owner)) 280 goto error; 281 282 sd = spi_get_drvdata(spi); 283 284 /* Register with the v4l2_device which increases the module's 285 use count as well. */ 286 if (v4l2_device_register_subdev(v4l2_dev, sd)) 287 sd = NULL; 288 289 /* Decrease the module use count to match the first try_module_get. */ 290 module_put(spi->dev.driver->owner); 291 292 error: 293 /* If we have a client but no subdev, then something went wrong and 294 we must unregister the client. */ 295 if (!sd) 296 spi_unregister_device(spi); 297 298 return sd; 299 } 300 EXPORT_SYMBOL_GPL(v4l2_spi_new_subdev); 301 302 #endif /* defined(CONFIG_SPI) */ 303 304 /* Clamp x to be between min and max, aligned to a multiple of 2^align. min 305 * and max don't have to be aligned, but there must be at least one valid 306 * value. E.g., min=17,max=31,align=4 is not allowed as there are no multiples 307 * of 16 between 17 and 31. */ 308 static unsigned int clamp_align(unsigned int x, unsigned int min, 309 unsigned int max, unsigned int align) 310 { 311 /* Bits that must be zero to be aligned */ 312 unsigned int mask = ~((1 << align) - 1); 313 314 /* Clamp to aligned min and max */ 315 x = clamp(x, (min + ~mask) & mask, max & mask); 316 317 /* Round to nearest aligned value */ 318 if (align) 319 x = (x + (1 << (align - 1))) & mask; 320 321 return x; 322 } 323 324 void v4l_bound_align_image(u32 *w, unsigned int wmin, unsigned int wmax, 325 unsigned int walign, 326 u32 *h, unsigned int hmin, unsigned int hmax, 327 unsigned int halign, unsigned int salign) 328 { 329 *w = clamp_align(*w, wmin, wmax, walign); 330 *h = clamp_align(*h, hmin, hmax, halign); 331 332 /* Usually we don't need to align the size and are done now. */ 333 if (!salign) 334 return; 335 336 /* How much alignment do we have? */ 337 walign = __ffs(*w); 338 halign = __ffs(*h); 339 /* Enough to satisfy the image alignment? */ 340 if (walign + halign < salign) { 341 /* Max walign where there is still a valid width */ 342 unsigned int wmaxa = __fls(wmax ^ (wmin - 1)); 343 /* Max halign where there is still a valid height */ 344 unsigned int hmaxa = __fls(hmax ^ (hmin - 1)); 345 346 /* up the smaller alignment until we have enough */ 347 do { 348 if (halign >= hmaxa || 349 (walign <= halign && walign < wmaxa)) { 350 *w = clamp_align(*w, wmin, wmax, walign + 1); 351 walign = __ffs(*w); 352 } else { 353 *h = clamp_align(*h, hmin, hmax, halign + 1); 354 halign = __ffs(*h); 355 } 356 } while (halign + walign < salign); 357 } 358 } 359 EXPORT_SYMBOL_GPL(v4l_bound_align_image); 360 361 const void * 362 __v4l2_find_nearest_size(const void *array, size_t array_size, 363 size_t entry_size, size_t width_offset, 364 size_t height_offset, s32 width, s32 height) 365 { 366 u32 error, min_error = U32_MAX; 367 const void *best = NULL; 368 unsigned int i; 369 370 if (!array) 371 return NULL; 372 373 for (i = 0; i < array_size; i++, array += entry_size) { 374 const u32 *entry_width = array + width_offset; 375 const u32 *entry_height = array + height_offset; 376 377 error = abs(*entry_width - width) + abs(*entry_height - height); 378 if (error > min_error) 379 continue; 380 381 min_error = error; 382 best = array; 383 if (!error) 384 break; 385 } 386 387 return best; 388 } 389 EXPORT_SYMBOL_GPL(__v4l2_find_nearest_size); 390 391 int v4l2_g_parm_cap(struct video_device *vdev, 392 struct v4l2_subdev *sd, struct v4l2_streamparm *a) 393 { 394 struct v4l2_subdev_frame_interval ival = { 0 }; 395 int ret; 396 397 if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && 398 a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) 399 return -EINVAL; 400 401 if (vdev->device_caps & V4L2_CAP_READWRITE) 402 a->parm.capture.readbuffers = 2; 403 if (v4l2_subdev_has_op(sd, video, g_frame_interval)) 404 a->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; 405 ret = v4l2_subdev_call(sd, video, g_frame_interval, &ival); 406 if (!ret) 407 a->parm.capture.timeperframe = ival.interval; 408 return ret; 409 } 410 EXPORT_SYMBOL_GPL(v4l2_g_parm_cap); 411 412 int v4l2_s_parm_cap(struct video_device *vdev, 413 struct v4l2_subdev *sd, struct v4l2_streamparm *a) 414 { 415 struct v4l2_subdev_frame_interval ival = { 416 .interval = a->parm.capture.timeperframe 417 }; 418 int ret; 419 420 if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && 421 a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) 422 return -EINVAL; 423 424 memset(&a->parm, 0, sizeof(a->parm)); 425 if (vdev->device_caps & V4L2_CAP_READWRITE) 426 a->parm.capture.readbuffers = 2; 427 else 428 a->parm.capture.readbuffers = 0; 429 430 if (v4l2_subdev_has_op(sd, video, g_frame_interval)) 431 a->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; 432 ret = v4l2_subdev_call(sd, video, s_frame_interval, &ival); 433 if (!ret) 434 a->parm.capture.timeperframe = ival.interval; 435 return ret; 436 } 437 EXPORT_SYMBOL_GPL(v4l2_s_parm_cap); 438 439 const struct v4l2_format_info *v4l2_format_info(u32 format) 440 { 441 static const struct v4l2_format_info formats[] = { 442 /* RGB formats */ 443 { .format = V4L2_PIX_FMT_BGR24, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, 444 { .format = V4L2_PIX_FMT_RGB24, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, 445 { .format = V4L2_PIX_FMT_HSV24, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, 446 { .format = V4L2_PIX_FMT_BGR32, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, 447 { .format = V4L2_PIX_FMT_XBGR32, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, 448 { .format = V4L2_PIX_FMT_RGB32, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, 449 { .format = V4L2_PIX_FMT_XRGB32, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, 450 { .format = V4L2_PIX_FMT_HSV32, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, 451 { .format = V4L2_PIX_FMT_ARGB32, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, 452 { .format = V4L2_PIX_FMT_ABGR32, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, 453 { .format = V4L2_PIX_FMT_GREY, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, 454 455 /* YUV packed formats */ 456 { .format = V4L2_PIX_FMT_YUYV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 }, 457 { .format = V4L2_PIX_FMT_YVYU, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 }, 458 { .format = V4L2_PIX_FMT_UYVY, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 }, 459 { .format = V4L2_PIX_FMT_VYUY, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 }, 460 461 /* YUV planar formats */ 462 { .format = V4L2_PIX_FMT_NV12, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 }, 463 { .format = V4L2_PIX_FMT_NV21, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 }, 464 { .format = V4L2_PIX_FMT_NV16, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 }, 465 { .format = V4L2_PIX_FMT_NV61, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 }, 466 { .format = V4L2_PIX_FMT_NV24, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 1, .vdiv = 1 }, 467 { .format = V4L2_PIX_FMT_NV42, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 1, .vdiv = 1 }, 468 469 { .format = V4L2_PIX_FMT_YUV410, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 4 }, 470 { .format = V4L2_PIX_FMT_YVU410, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 4 }, 471 { .format = V4L2_PIX_FMT_YUV411P, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 1 }, 472 { .format = V4L2_PIX_FMT_YUV420, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 2 }, 473 { .format = V4L2_PIX_FMT_YVU420, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 2 }, 474 { .format = V4L2_PIX_FMT_YUV422P, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 1 }, 475 476 /* YUV planar formats, non contiguous variant */ 477 { .format = V4L2_PIX_FMT_YUV420M, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 2 }, 478 { .format = V4L2_PIX_FMT_YVU420M, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 2 }, 479 { .format = V4L2_PIX_FMT_YUV422M, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 1 }, 480 { .format = V4L2_PIX_FMT_YVU422M, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 1 }, 481 { .format = V4L2_PIX_FMT_YUV444M, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 1, .vdiv = 1 }, 482 { .format = V4L2_PIX_FMT_YVU444M, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 1, .vdiv = 1 }, 483 484 { .format = V4L2_PIX_FMT_NV12M, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 }, 485 { .format = V4L2_PIX_FMT_NV21M, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 }, 486 { .format = V4L2_PIX_FMT_NV16M, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 }, 487 { .format = V4L2_PIX_FMT_NV61M, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 }, 488 489 /* Bayer RGB formats */ 490 { .format = V4L2_PIX_FMT_SBGGR8, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, 491 { .format = V4L2_PIX_FMT_SGBRG8, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, 492 { .format = V4L2_PIX_FMT_SGRBG8, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, 493 { .format = V4L2_PIX_FMT_SRGGB8, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, 494 { .format = V4L2_PIX_FMT_SBGGR10, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, 495 { .format = V4L2_PIX_FMT_SGBRG10, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, 496 { .format = V4L2_PIX_FMT_SGRBG10, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, 497 { .format = V4L2_PIX_FMT_SRGGB10, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, 498 { .format = V4L2_PIX_FMT_SBGGR10ALAW8, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, 499 { .format = V4L2_PIX_FMT_SGBRG10ALAW8, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, 500 { .format = V4L2_PIX_FMT_SGRBG10ALAW8, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, 501 { .format = V4L2_PIX_FMT_SRGGB10ALAW8, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, 502 { .format = V4L2_PIX_FMT_SBGGR10DPCM8, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, 503 { .format = V4L2_PIX_FMT_SGBRG10DPCM8, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, 504 { .format = V4L2_PIX_FMT_SGRBG10DPCM8, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, 505 { .format = V4L2_PIX_FMT_SRGGB10DPCM8, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, 506 { .format = V4L2_PIX_FMT_SBGGR12, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, 507 { .format = V4L2_PIX_FMT_SGBRG12, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, 508 { .format = V4L2_PIX_FMT_SGRBG12, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, 509 { .format = V4L2_PIX_FMT_SRGGB12, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, 510 }; 511 unsigned int i; 512 513 for (i = 0; i < ARRAY_SIZE(formats); ++i) 514 if (formats[i].format == format) 515 return &formats[i]; 516 return NULL; 517 } 518 EXPORT_SYMBOL(v4l2_format_info); 519 520 static inline unsigned int v4l2_format_block_width(const struct v4l2_format_info *info, int plane) 521 { 522 if (!info->block_w[plane]) 523 return 1; 524 return info->block_w[plane]; 525 } 526 527 static inline unsigned int v4l2_format_block_height(const struct v4l2_format_info *info, int plane) 528 { 529 if (!info->block_h[plane]) 530 return 1; 531 return info->block_h[plane]; 532 } 533 534 int v4l2_fill_pixfmt_mp(struct v4l2_pix_format_mplane *pixfmt, 535 int pixelformat, int width, int height) 536 { 537 const struct v4l2_format_info *info; 538 struct v4l2_plane_pix_format *plane; 539 int i; 540 541 info = v4l2_format_info(pixelformat); 542 if (!info) 543 return -EINVAL; 544 545 pixfmt->width = width; 546 pixfmt->height = height; 547 pixfmt->pixelformat = pixelformat; 548 pixfmt->num_planes = info->mem_planes; 549 550 if (info->mem_planes == 1) { 551 plane = &pixfmt->plane_fmt[0]; 552 plane->bytesperline = ALIGN(width, v4l2_format_block_width(info, 0)) * info->bpp[0]; 553 plane->sizeimage = 0; 554 555 for (i = 0; i < info->comp_planes; i++) { 556 unsigned int hdiv = (i == 0) ? 1 : info->hdiv; 557 unsigned int vdiv = (i == 0) ? 1 : info->vdiv; 558 unsigned int aligned_width; 559 unsigned int aligned_height; 560 561 aligned_width = ALIGN(width, v4l2_format_block_width(info, i)); 562 aligned_height = ALIGN(height, v4l2_format_block_height(info, i)); 563 564 plane->sizeimage += info->bpp[i] * 565 DIV_ROUND_UP(aligned_width, hdiv) * 566 DIV_ROUND_UP(aligned_height, vdiv); 567 } 568 } else { 569 for (i = 0; i < info->comp_planes; i++) { 570 unsigned int hdiv = (i == 0) ? 1 : info->hdiv; 571 unsigned int vdiv = (i == 0) ? 1 : info->vdiv; 572 unsigned int aligned_width; 573 unsigned int aligned_height; 574 575 aligned_width = ALIGN(width, v4l2_format_block_width(info, i)); 576 aligned_height = ALIGN(height, v4l2_format_block_height(info, i)); 577 578 plane = &pixfmt->plane_fmt[i]; 579 plane->bytesperline = 580 info->bpp[i] * DIV_ROUND_UP(aligned_width, hdiv); 581 plane->sizeimage = 582 plane->bytesperline * DIV_ROUND_UP(aligned_height, vdiv); 583 } 584 } 585 return 0; 586 } 587 EXPORT_SYMBOL_GPL(v4l2_fill_pixfmt_mp); 588 589 int v4l2_fill_pixfmt(struct v4l2_pix_format *pixfmt, int pixelformat, int width, int height) 590 { 591 const struct v4l2_format_info *info; 592 int i; 593 594 info = v4l2_format_info(pixelformat); 595 if (!info) 596 return -EINVAL; 597 598 /* Single planar API cannot be used for multi plane formats. */ 599 if (info->mem_planes > 1) 600 return -EINVAL; 601 602 pixfmt->width = width; 603 pixfmt->height = height; 604 pixfmt->pixelformat = pixelformat; 605 pixfmt->bytesperline = ALIGN(width, v4l2_format_block_width(info, 0)) * info->bpp[0]; 606 pixfmt->sizeimage = 0; 607 608 for (i = 0; i < info->comp_planes; i++) { 609 unsigned int hdiv = (i == 0) ? 1 : info->hdiv; 610 unsigned int vdiv = (i == 0) ? 1 : info->vdiv; 611 unsigned int aligned_width; 612 unsigned int aligned_height; 613 614 aligned_width = ALIGN(width, v4l2_format_block_width(info, i)); 615 aligned_height = ALIGN(height, v4l2_format_block_height(info, i)); 616 617 pixfmt->sizeimage += info->bpp[i] * 618 DIV_ROUND_UP(aligned_width, hdiv) * 619 DIV_ROUND_UP(aligned_height, vdiv); 620 } 621 return 0; 622 } 623 EXPORT_SYMBOL_GPL(v4l2_fill_pixfmt); 624