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