Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.2 845 lines 21 kB view raw
1/* 2 * vivid-vid-common.c - common video support functions. 3 * 4 * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved. 5 * 6 * This program is free software; you may redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; version 2 of the License. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 11 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 12 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 13 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 14 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 15 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 16 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 * SOFTWARE. 18 */ 19 20#include <linux/errno.h> 21#include <linux/kernel.h> 22#include <linux/sched.h> 23#include <linux/videodev2.h> 24#include <linux/v4l2-dv-timings.h> 25#include <media/v4l2-common.h> 26#include <media/v4l2-event.h> 27#include <media/v4l2-dv-timings.h> 28 29#include "vivid-core.h" 30#include "vivid-vid-common.h" 31 32const struct v4l2_dv_timings_cap vivid_dv_timings_cap = { 33 .type = V4L2_DV_BT_656_1120, 34 /* keep this initialization for compatibility with GCC < 4.4.6 */ 35 .reserved = { 0 }, 36 V4L2_INIT_BT_TIMINGS(0, MAX_WIDTH, 0, MAX_HEIGHT, 14000000, 775000000, 37 V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT | 38 V4L2_DV_BT_STD_CVT | V4L2_DV_BT_STD_GTF, 39 V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_INTERLACED) 40}; 41 42/* ------------------------------------------------------------------ 43 Basic structures 44 ------------------------------------------------------------------*/ 45 46struct vivid_fmt vivid_formats[] = { 47 { 48 .fourcc = V4L2_PIX_FMT_YUYV, 49 .vdownsampling = { 1 }, 50 .bit_depth = { 16 }, 51 .is_yuv = true, 52 .planes = 1, 53 .buffers = 1, 54 .data_offset = { PLANE0_DATA_OFFSET }, 55 }, 56 { 57 .fourcc = V4L2_PIX_FMT_UYVY, 58 .vdownsampling = { 1 }, 59 .bit_depth = { 16 }, 60 .is_yuv = true, 61 .planes = 1, 62 .buffers = 1, 63 }, 64 { 65 .fourcc = V4L2_PIX_FMT_YVYU, 66 .vdownsampling = { 1 }, 67 .bit_depth = { 16 }, 68 .is_yuv = true, 69 .planes = 1, 70 .buffers = 1, 71 }, 72 { 73 .fourcc = V4L2_PIX_FMT_VYUY, 74 .vdownsampling = { 1 }, 75 .bit_depth = { 16 }, 76 .is_yuv = true, 77 .planes = 1, 78 .buffers = 1, 79 }, 80 { 81 .fourcc = V4L2_PIX_FMT_YUV422P, 82 .vdownsampling = { 1, 1, 1 }, 83 .bit_depth = { 8, 4, 4 }, 84 .is_yuv = true, 85 .planes = 3, 86 .buffers = 1, 87 }, 88 { 89 .fourcc = V4L2_PIX_FMT_YUV420, 90 .vdownsampling = { 1, 2, 2 }, 91 .bit_depth = { 8, 4, 4 }, 92 .is_yuv = true, 93 .planes = 3, 94 .buffers = 1, 95 }, 96 { 97 .fourcc = V4L2_PIX_FMT_YVU420, 98 .vdownsampling = { 1, 2, 2 }, 99 .bit_depth = { 8, 4, 4 }, 100 .is_yuv = true, 101 .planes = 3, 102 .buffers = 1, 103 }, 104 { 105 .fourcc = V4L2_PIX_FMT_NV12, 106 .vdownsampling = { 1, 2 }, 107 .bit_depth = { 8, 8 }, 108 .is_yuv = true, 109 .planes = 2, 110 .buffers = 1, 111 }, 112 { 113 .fourcc = V4L2_PIX_FMT_NV21, 114 .vdownsampling = { 1, 2 }, 115 .bit_depth = { 8, 8 }, 116 .is_yuv = true, 117 .planes = 2, 118 .buffers = 1, 119 }, 120 { 121 .fourcc = V4L2_PIX_FMT_NV16, 122 .vdownsampling = { 1, 1 }, 123 .bit_depth = { 8, 8 }, 124 .is_yuv = true, 125 .planes = 2, 126 .buffers = 1, 127 }, 128 { 129 .fourcc = V4L2_PIX_FMT_NV61, 130 .vdownsampling = { 1, 1 }, 131 .bit_depth = { 8, 8 }, 132 .is_yuv = true, 133 .planes = 2, 134 .buffers = 1, 135 }, 136 { 137 .fourcc = V4L2_PIX_FMT_NV24, 138 .vdownsampling = { 1, 1 }, 139 .bit_depth = { 8, 16 }, 140 .is_yuv = true, 141 .planes = 2, 142 .buffers = 1, 143 }, 144 { 145 .fourcc = V4L2_PIX_FMT_NV42, 146 .vdownsampling = { 1, 1 }, 147 .bit_depth = { 8, 16 }, 148 .is_yuv = true, 149 .planes = 2, 150 .buffers = 1, 151 }, 152 { 153 .fourcc = V4L2_PIX_FMT_YUV555, /* uuuvvvvv ayyyyyuu */ 154 .vdownsampling = { 1 }, 155 .bit_depth = { 16 }, 156 .planes = 1, 157 .buffers = 1, 158 .alpha_mask = 0x8000, 159 }, 160 { 161 .fourcc = V4L2_PIX_FMT_YUV565, /* uuuvvvvv yyyyyuuu */ 162 .vdownsampling = { 1 }, 163 .bit_depth = { 16 }, 164 .planes = 1, 165 .buffers = 1, 166 }, 167 { 168 .fourcc = V4L2_PIX_FMT_YUV444, /* uuuuvvvv aaaayyyy */ 169 .vdownsampling = { 1 }, 170 .bit_depth = { 16 }, 171 .planes = 1, 172 .buffers = 1, 173 .alpha_mask = 0xf000, 174 }, 175 { 176 .fourcc = V4L2_PIX_FMT_YUV32, /* ayuv */ 177 .vdownsampling = { 1 }, 178 .bit_depth = { 32 }, 179 .planes = 1, 180 .buffers = 1, 181 .alpha_mask = 0x000000ff, 182 }, 183 { 184 .fourcc = V4L2_PIX_FMT_GREY, 185 .vdownsampling = { 1 }, 186 .bit_depth = { 8 }, 187 .is_yuv = true, 188 .planes = 1, 189 .buffers = 1, 190 }, 191 { 192 .fourcc = V4L2_PIX_FMT_Y16, 193 .vdownsampling = { 1 }, 194 .bit_depth = { 16 }, 195 .is_yuv = true, 196 .planes = 1, 197 .buffers = 1, 198 }, 199 { 200 .fourcc = V4L2_PIX_FMT_Y16_BE, 201 .vdownsampling = { 1 }, 202 .bit_depth = { 16 }, 203 .is_yuv = true, 204 .planes = 1, 205 .buffers = 1, 206 }, 207 { 208 .fourcc = V4L2_PIX_FMT_RGB332, /* rrrgggbb */ 209 .vdownsampling = { 1 }, 210 .bit_depth = { 8 }, 211 .planes = 1, 212 .buffers = 1, 213 }, 214 { 215 .fourcc = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */ 216 .vdownsampling = { 1 }, 217 .bit_depth = { 16 }, 218 .planes = 1, 219 .buffers = 1, 220 .can_do_overlay = true, 221 }, 222 { 223 .fourcc = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */ 224 .vdownsampling = { 1 }, 225 .bit_depth = { 16 }, 226 .planes = 1, 227 .buffers = 1, 228 .can_do_overlay = true, 229 }, 230 { 231 .fourcc = V4L2_PIX_FMT_RGB444, /* xxxxrrrr ggggbbbb */ 232 .vdownsampling = { 1 }, 233 .bit_depth = { 16 }, 234 .planes = 1, 235 .buffers = 1, 236 }, 237 { 238 .fourcc = V4L2_PIX_FMT_XRGB444, /* xxxxrrrr ggggbbbb */ 239 .vdownsampling = { 1 }, 240 .bit_depth = { 16 }, 241 .planes = 1, 242 .buffers = 1, 243 }, 244 { 245 .fourcc = V4L2_PIX_FMT_ARGB444, /* aaaarrrr ggggbbbb */ 246 .vdownsampling = { 1 }, 247 .bit_depth = { 16 }, 248 .planes = 1, 249 .buffers = 1, 250 .alpha_mask = 0x00f0, 251 }, 252 { 253 .fourcc = V4L2_PIX_FMT_RGB555, /* gggbbbbb xrrrrrgg */ 254 .vdownsampling = { 1 }, 255 .bit_depth = { 16 }, 256 .planes = 1, 257 .buffers = 1, 258 .can_do_overlay = true, 259 }, 260 { 261 .fourcc = V4L2_PIX_FMT_XRGB555, /* gggbbbbb xrrrrrgg */ 262 .vdownsampling = { 1 }, 263 .bit_depth = { 16 }, 264 .planes = 1, 265 .buffers = 1, 266 .can_do_overlay = true, 267 }, 268 { 269 .fourcc = V4L2_PIX_FMT_ARGB555, /* gggbbbbb arrrrrgg */ 270 .vdownsampling = { 1 }, 271 .bit_depth = { 16 }, 272 .planes = 1, 273 .buffers = 1, 274 .can_do_overlay = true, 275 .alpha_mask = 0x8000, 276 }, 277 { 278 .fourcc = V4L2_PIX_FMT_RGB555X, /* xrrrrrgg gggbbbbb */ 279 .vdownsampling = { 1 }, 280 .bit_depth = { 16 }, 281 .planes = 1, 282 .buffers = 1, 283 }, 284 { 285 .fourcc = V4L2_PIX_FMT_XRGB555X, /* xrrrrrgg gggbbbbb */ 286 .vdownsampling = { 1 }, 287 .bit_depth = { 16 }, 288 .planes = 1, 289 .buffers = 1, 290 }, 291 { 292 .fourcc = V4L2_PIX_FMT_ARGB555X, /* arrrrrgg gggbbbbb */ 293 .vdownsampling = { 1 }, 294 .bit_depth = { 16 }, 295 .planes = 1, 296 .buffers = 1, 297 .alpha_mask = 0x0080, 298 }, 299 { 300 .fourcc = V4L2_PIX_FMT_RGB24, /* rgb */ 301 .vdownsampling = { 1 }, 302 .bit_depth = { 24 }, 303 .planes = 1, 304 .buffers = 1, 305 }, 306 { 307 .fourcc = V4L2_PIX_FMT_BGR24, /* bgr */ 308 .vdownsampling = { 1 }, 309 .bit_depth = { 24 }, 310 .planes = 1, 311 .buffers = 1, 312 }, 313 { 314 .fourcc = V4L2_PIX_FMT_BGR666, /* bbbbbbgg ggggrrrr rrxxxxxx */ 315 .vdownsampling = { 1 }, 316 .bit_depth = { 32 }, 317 .planes = 1, 318 .buffers = 1, 319 }, 320 { 321 .fourcc = V4L2_PIX_FMT_RGB32, /* xrgb */ 322 .vdownsampling = { 1 }, 323 .bit_depth = { 32 }, 324 .planes = 1, 325 .buffers = 1, 326 }, 327 { 328 .fourcc = V4L2_PIX_FMT_BGR32, /* bgrx */ 329 .vdownsampling = { 1 }, 330 .bit_depth = { 32 }, 331 .planes = 1, 332 .buffers = 1, 333 }, 334 { 335 .fourcc = V4L2_PIX_FMT_XRGB32, /* xrgb */ 336 .vdownsampling = { 1 }, 337 .bit_depth = { 32 }, 338 .planes = 1, 339 .buffers = 1, 340 }, 341 { 342 .fourcc = V4L2_PIX_FMT_XBGR32, /* bgrx */ 343 .vdownsampling = { 1 }, 344 .bit_depth = { 32 }, 345 .planes = 1, 346 .buffers = 1, 347 }, 348 { 349 .fourcc = V4L2_PIX_FMT_ARGB32, /* argb */ 350 .vdownsampling = { 1 }, 351 .bit_depth = { 32 }, 352 .planes = 1, 353 .buffers = 1, 354 .alpha_mask = 0x000000ff, 355 }, 356 { 357 .fourcc = V4L2_PIX_FMT_ABGR32, /* bgra */ 358 .vdownsampling = { 1 }, 359 .bit_depth = { 32 }, 360 .planes = 1, 361 .buffers = 1, 362 .alpha_mask = 0xff000000, 363 }, 364 { 365 .fourcc = V4L2_PIX_FMT_SBGGR8, /* Bayer BG/GR */ 366 .vdownsampling = { 1 }, 367 .bit_depth = { 8 }, 368 .planes = 1, 369 .buffers = 1, 370 }, 371 { 372 .fourcc = V4L2_PIX_FMT_SGBRG8, /* Bayer GB/RG */ 373 .vdownsampling = { 1 }, 374 .bit_depth = { 8 }, 375 .planes = 1, 376 .buffers = 1, 377 }, 378 { 379 .fourcc = V4L2_PIX_FMT_SGRBG8, /* Bayer GR/BG */ 380 .vdownsampling = { 1 }, 381 .bit_depth = { 8 }, 382 .planes = 1, 383 .buffers = 1, 384 }, 385 { 386 .fourcc = V4L2_PIX_FMT_SRGGB8, /* Bayer RG/GB */ 387 .vdownsampling = { 1 }, 388 .bit_depth = { 8 }, 389 .planes = 1, 390 .buffers = 1, 391 }, 392 { 393 .fourcc = V4L2_PIX_FMT_NV16M, 394 .vdownsampling = { 1, 1 }, 395 .bit_depth = { 8, 8 }, 396 .is_yuv = true, 397 .planes = 2, 398 .buffers = 2, 399 .data_offset = { PLANE0_DATA_OFFSET, 0 }, 400 }, 401 { 402 .fourcc = V4L2_PIX_FMT_NV61M, 403 .vdownsampling = { 1, 1 }, 404 .bit_depth = { 8, 8 }, 405 .is_yuv = true, 406 .planes = 2, 407 .buffers = 2, 408 .data_offset = { 0, PLANE0_DATA_OFFSET }, 409 }, 410 { 411 .fourcc = V4L2_PIX_FMT_YUV420M, 412 .vdownsampling = { 1, 2, 2 }, 413 .bit_depth = { 8, 4, 4 }, 414 .is_yuv = true, 415 .planes = 3, 416 .buffers = 3, 417 }, 418 { 419 .fourcc = V4L2_PIX_FMT_YVU420M, 420 .vdownsampling = { 1, 2, 2 }, 421 .bit_depth = { 8, 4, 4 }, 422 .is_yuv = true, 423 .planes = 3, 424 .buffers = 3, 425 }, 426 { 427 .fourcc = V4L2_PIX_FMT_NV12M, 428 .vdownsampling = { 1, 2 }, 429 .bit_depth = { 8, 8 }, 430 .is_yuv = true, 431 .planes = 2, 432 .buffers = 2, 433 }, 434 { 435 .fourcc = V4L2_PIX_FMT_NV21M, 436 .vdownsampling = { 1, 2 }, 437 .bit_depth = { 8, 8 }, 438 .is_yuv = true, 439 .planes = 2, 440 .buffers = 2, 441 }, 442}; 443 444/* There are 6 multiplanar formats in the list */ 445#define VIVID_MPLANAR_FORMATS 6 446 447const struct vivid_fmt *vivid_get_format(struct vivid_dev *dev, u32 pixelformat) 448{ 449 const struct vivid_fmt *fmt; 450 unsigned k; 451 452 for (k = 0; k < ARRAY_SIZE(vivid_formats); k++) { 453 fmt = &vivid_formats[k]; 454 if (fmt->fourcc == pixelformat) 455 if (fmt->buffers == 1 || dev->multiplanar) 456 return fmt; 457 } 458 459 return NULL; 460} 461 462bool vivid_vid_can_loop(struct vivid_dev *dev) 463{ 464 if (dev->src_rect.width != dev->sink_rect.width || 465 dev->src_rect.height != dev->sink_rect.height) 466 return false; 467 if (dev->fmt_cap->fourcc != dev->fmt_out->fourcc) 468 return false; 469 if (dev->field_cap != dev->field_out) 470 return false; 471 /* 472 * While this can be supported, it is just too much work 473 * to actually implement. 474 */ 475 if (dev->field_cap == V4L2_FIELD_SEQ_TB || 476 dev->field_cap == V4L2_FIELD_SEQ_BT) 477 return false; 478 if (vivid_is_svid_cap(dev) && vivid_is_svid_out(dev)) { 479 if (!(dev->std_cap & V4L2_STD_525_60) != 480 !(dev->std_out & V4L2_STD_525_60)) 481 return false; 482 return true; 483 } 484 if (vivid_is_hdmi_cap(dev) && vivid_is_hdmi_out(dev)) 485 return true; 486 return false; 487} 488 489void vivid_send_source_change(struct vivid_dev *dev, unsigned type) 490{ 491 struct v4l2_event ev = { 492 .type = V4L2_EVENT_SOURCE_CHANGE, 493 .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION, 494 }; 495 unsigned i; 496 497 for (i = 0; i < dev->num_inputs; i++) { 498 ev.id = i; 499 if (dev->input_type[i] == type) { 500 if (video_is_registered(&dev->vid_cap_dev) && dev->has_vid_cap) 501 v4l2_event_queue(&dev->vid_cap_dev, &ev); 502 if (video_is_registered(&dev->vbi_cap_dev) && dev->has_vbi_cap) 503 v4l2_event_queue(&dev->vbi_cap_dev, &ev); 504 } 505 } 506} 507 508/* 509 * Conversion function that converts a single-planar format to a 510 * single-plane multiplanar format. 511 */ 512void fmt_sp2mp(const struct v4l2_format *sp_fmt, struct v4l2_format *mp_fmt) 513{ 514 struct v4l2_pix_format_mplane *mp = &mp_fmt->fmt.pix_mp; 515 struct v4l2_plane_pix_format *ppix = &mp->plane_fmt[0]; 516 const struct v4l2_pix_format *pix = &sp_fmt->fmt.pix; 517 bool is_out = sp_fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT; 518 519 memset(mp->reserved, 0, sizeof(mp->reserved)); 520 mp_fmt->type = is_out ? V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE : 521 V4L2_CAP_VIDEO_CAPTURE_MPLANE; 522 mp->width = pix->width; 523 mp->height = pix->height; 524 mp->pixelformat = pix->pixelformat; 525 mp->field = pix->field; 526 mp->colorspace = pix->colorspace; 527 mp->xfer_func = pix->xfer_func; 528 mp->ycbcr_enc = pix->ycbcr_enc; 529 mp->quantization = pix->quantization; 530 mp->num_planes = 1; 531 mp->flags = pix->flags; 532 ppix->sizeimage = pix->sizeimage; 533 ppix->bytesperline = pix->bytesperline; 534 memset(ppix->reserved, 0, sizeof(ppix->reserved)); 535} 536 537int fmt_sp2mp_func(struct file *file, void *priv, 538 struct v4l2_format *f, fmtfunc func) 539{ 540 struct v4l2_format fmt; 541 struct v4l2_pix_format_mplane *mp = &fmt.fmt.pix_mp; 542 struct v4l2_plane_pix_format *ppix = &mp->plane_fmt[0]; 543 struct v4l2_pix_format *pix = &f->fmt.pix; 544 int ret; 545 546 /* Converts to a mplane format */ 547 fmt_sp2mp(f, &fmt); 548 /* Passes it to the generic mplane format function */ 549 ret = func(file, priv, &fmt); 550 /* Copies back the mplane data to the single plane format */ 551 pix->width = mp->width; 552 pix->height = mp->height; 553 pix->pixelformat = mp->pixelformat; 554 pix->field = mp->field; 555 pix->colorspace = mp->colorspace; 556 pix->xfer_func = mp->xfer_func; 557 pix->ycbcr_enc = mp->ycbcr_enc; 558 pix->quantization = mp->quantization; 559 pix->sizeimage = ppix->sizeimage; 560 pix->bytesperline = ppix->bytesperline; 561 pix->flags = mp->flags; 562 return ret; 563} 564 565/* v4l2_rect helper function: copy the width/height values */ 566void rect_set_size_to(struct v4l2_rect *r, const struct v4l2_rect *size) 567{ 568 r->width = size->width; 569 r->height = size->height; 570} 571 572/* v4l2_rect helper function: width and height of r should be >= min_size */ 573void rect_set_min_size(struct v4l2_rect *r, const struct v4l2_rect *min_size) 574{ 575 if (r->width < min_size->width) 576 r->width = min_size->width; 577 if (r->height < min_size->height) 578 r->height = min_size->height; 579} 580 581/* v4l2_rect helper function: width and height of r should be <= max_size */ 582void rect_set_max_size(struct v4l2_rect *r, const struct v4l2_rect *max_size) 583{ 584 if (r->width > max_size->width) 585 r->width = max_size->width; 586 if (r->height > max_size->height) 587 r->height = max_size->height; 588} 589 590/* v4l2_rect helper function: r should be inside boundary */ 591void rect_map_inside(struct v4l2_rect *r, const struct v4l2_rect *boundary) 592{ 593 rect_set_max_size(r, boundary); 594 if (r->left < boundary->left) 595 r->left = boundary->left; 596 if (r->top < boundary->top) 597 r->top = boundary->top; 598 if (r->left + r->width > boundary->width) 599 r->left = boundary->width - r->width; 600 if (r->top + r->height > boundary->height) 601 r->top = boundary->height - r->height; 602} 603 604/* v4l2_rect helper function: return true if r1 has the same size as r2 */ 605bool rect_same_size(const struct v4l2_rect *r1, const struct v4l2_rect *r2) 606{ 607 return r1->width == r2->width && r1->height == r2->height; 608} 609 610/* v4l2_rect helper function: calculate the intersection of two rects */ 611struct v4l2_rect rect_intersect(const struct v4l2_rect *a, const struct v4l2_rect *b) 612{ 613 struct v4l2_rect r; 614 int right, bottom; 615 616 r.top = max(a->top, b->top); 617 r.left = max(a->left, b->left); 618 bottom = min(a->top + a->height, b->top + b->height); 619 right = min(a->left + a->width, b->left + b->width); 620 r.height = max(0, bottom - r.top); 621 r.width = max(0, right - r.left); 622 return r; 623} 624 625/* 626 * v4l2_rect helper function: scale rect r by to->width / from->width and 627 * to->height / from->height. 628 */ 629void rect_scale(struct v4l2_rect *r, const struct v4l2_rect *from, 630 const struct v4l2_rect *to) 631{ 632 if (from->width == 0 || from->height == 0) { 633 r->left = r->top = r->width = r->height = 0; 634 return; 635 } 636 r->left = (((r->left - from->left) * to->width) / from->width) & ~1; 637 r->width = ((r->width * to->width) / from->width) & ~1; 638 r->top = ((r->top - from->top) * to->height) / from->height; 639 r->height = (r->height * to->height) / from->height; 640} 641 642bool rect_overlap(const struct v4l2_rect *r1, const struct v4l2_rect *r2) 643{ 644 /* 645 * IF the left side of r1 is to the right of the right side of r2 OR 646 * the left side of r2 is to the right of the right side of r1 THEN 647 * they do not overlap. 648 */ 649 if (r1->left >= r2->left + r2->width || 650 r2->left >= r1->left + r1->width) 651 return false; 652 /* 653 * IF the top side of r1 is below the bottom of r2 OR 654 * the top side of r2 is below the bottom of r1 THEN 655 * they do not overlap. 656 */ 657 if (r1->top >= r2->top + r2->height || 658 r2->top >= r1->top + r1->height) 659 return false; 660 return true; 661} 662int vivid_vid_adjust_sel(unsigned flags, struct v4l2_rect *r) 663{ 664 unsigned w = r->width; 665 unsigned h = r->height; 666 667 /* sanitize w and h in case someone passes ~0 as the value */ 668 w &= 0xffff; 669 h &= 0xffff; 670 if (!(flags & V4L2_SEL_FLAG_LE)) { 671 w++; 672 h++; 673 if (w < 2) 674 w = 2; 675 if (h < 2) 676 h = 2; 677 } 678 if (!(flags & V4L2_SEL_FLAG_GE)) { 679 if (w > MAX_WIDTH) 680 w = MAX_WIDTH; 681 if (h > MAX_HEIGHT) 682 h = MAX_HEIGHT; 683 } 684 w = w & ~1; 685 h = h & ~1; 686 if (w < 2 || h < 2) 687 return -ERANGE; 688 if (w > MAX_WIDTH || h > MAX_HEIGHT) 689 return -ERANGE; 690 if (r->top < 0) 691 r->top = 0; 692 if (r->left < 0) 693 r->left = 0; 694 /* sanitize left and top in case someone passes ~0 as the value */ 695 r->left &= 0xfffe; 696 r->top &= 0xfffe; 697 if (r->left + w > MAX_WIDTH) 698 r->left = MAX_WIDTH - w; 699 if (r->top + h > MAX_HEIGHT) 700 r->top = MAX_HEIGHT - h; 701 if ((flags & (V4L2_SEL_FLAG_GE | V4L2_SEL_FLAG_LE)) == 702 (V4L2_SEL_FLAG_GE | V4L2_SEL_FLAG_LE) && 703 (r->width != w || r->height != h)) 704 return -ERANGE; 705 r->width = w; 706 r->height = h; 707 return 0; 708} 709 710int vivid_enum_fmt_vid(struct file *file, void *priv, 711 struct v4l2_fmtdesc *f) 712{ 713 struct vivid_dev *dev = video_drvdata(file); 714 const struct vivid_fmt *fmt; 715 716 if (f->index >= ARRAY_SIZE(vivid_formats) - 717 (dev->multiplanar ? 0 : VIVID_MPLANAR_FORMATS)) 718 return -EINVAL; 719 720 fmt = &vivid_formats[f->index]; 721 722 f->pixelformat = fmt->fourcc; 723 return 0; 724} 725 726int vidioc_enum_fmt_vid_mplane(struct file *file, void *priv, 727 struct v4l2_fmtdesc *f) 728{ 729 struct vivid_dev *dev = video_drvdata(file); 730 731 if (!dev->multiplanar) 732 return -ENOTTY; 733 return vivid_enum_fmt_vid(file, priv, f); 734} 735 736int vidioc_enum_fmt_vid(struct file *file, void *priv, 737 struct v4l2_fmtdesc *f) 738{ 739 struct vivid_dev *dev = video_drvdata(file); 740 741 if (dev->multiplanar) 742 return -ENOTTY; 743 return vivid_enum_fmt_vid(file, priv, f); 744} 745 746int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id) 747{ 748 struct vivid_dev *dev = video_drvdata(file); 749 struct video_device *vdev = video_devdata(file); 750 751 if (vdev->vfl_dir == VFL_DIR_RX) { 752 if (!vivid_is_sdtv_cap(dev)) 753 return -ENODATA; 754 *id = dev->std_cap; 755 } else { 756 if (!vivid_is_svid_out(dev)) 757 return -ENODATA; 758 *id = dev->std_out; 759 } 760 return 0; 761} 762 763int vidioc_g_dv_timings(struct file *file, void *_fh, 764 struct v4l2_dv_timings *timings) 765{ 766 struct vivid_dev *dev = video_drvdata(file); 767 struct video_device *vdev = video_devdata(file); 768 769 if (vdev->vfl_dir == VFL_DIR_RX) { 770 if (!vivid_is_hdmi_cap(dev)) 771 return -ENODATA; 772 *timings = dev->dv_timings_cap; 773 } else { 774 if (!vivid_is_hdmi_out(dev)) 775 return -ENODATA; 776 *timings = dev->dv_timings_out; 777 } 778 return 0; 779} 780 781int vidioc_enum_dv_timings(struct file *file, void *_fh, 782 struct v4l2_enum_dv_timings *timings) 783{ 784 struct vivid_dev *dev = video_drvdata(file); 785 struct video_device *vdev = video_devdata(file); 786 787 if (vdev->vfl_dir == VFL_DIR_RX) { 788 if (!vivid_is_hdmi_cap(dev)) 789 return -ENODATA; 790 } else { 791 if (!vivid_is_hdmi_out(dev)) 792 return -ENODATA; 793 } 794 return v4l2_enum_dv_timings_cap(timings, &vivid_dv_timings_cap, 795 NULL, NULL); 796} 797 798int vidioc_dv_timings_cap(struct file *file, void *_fh, 799 struct v4l2_dv_timings_cap *cap) 800{ 801 struct vivid_dev *dev = video_drvdata(file); 802 struct video_device *vdev = video_devdata(file); 803 804 if (vdev->vfl_dir == VFL_DIR_RX) { 805 if (!vivid_is_hdmi_cap(dev)) 806 return -ENODATA; 807 } else { 808 if (!vivid_is_hdmi_out(dev)) 809 return -ENODATA; 810 } 811 *cap = vivid_dv_timings_cap; 812 return 0; 813} 814 815int vidioc_g_edid(struct file *file, void *_fh, 816 struct v4l2_edid *edid) 817{ 818 struct vivid_dev *dev = video_drvdata(file); 819 struct video_device *vdev = video_devdata(file); 820 821 memset(edid->reserved, 0, sizeof(edid->reserved)); 822 if (vdev->vfl_dir == VFL_DIR_RX) { 823 if (edid->pad >= dev->num_inputs) 824 return -EINVAL; 825 if (dev->input_type[edid->pad] != HDMI) 826 return -EINVAL; 827 } else { 828 if (edid->pad >= dev->num_outputs) 829 return -EINVAL; 830 if (dev->output_type[edid->pad] != HDMI) 831 return -EINVAL; 832 } 833 if (edid->start_block == 0 && edid->blocks == 0) { 834 edid->blocks = dev->edid_blocks; 835 return 0; 836 } 837 if (dev->edid_blocks == 0) 838 return -ENODATA; 839 if (edid->start_block >= dev->edid_blocks) 840 return -EINVAL; 841 if (edid->start_block + edid->blocks > dev->edid_blocks) 842 edid->blocks = dev->edid_blocks - edid->start_block; 843 memcpy(edid->edid, dev->edid, edid->blocks * 128); 844 return 0; 845}