1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * vivid-vid-common.c - common video support functions. 4 * 5 * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved. 6 */ 7 8 #include <linux/errno.h> 9 #include <linux/kernel.h> 10 #include <linux/sched.h> 11 #include <linux/videodev2.h> 12 #include <linux/v4l2-dv-timings.h> 13 #include <media/v4l2-common.h> 14 #include <media/v4l2-event.h> 15 #include <media/v4l2-dv-timings.h> 16 17 #include "vivid-core.h" 18 #include "vivid-vid-common.h" 19 20 const struct v4l2_dv_timings_cap vivid_dv_timings_cap = { 21 .type = V4L2_DV_BT_656_1120, 22 /* keep this initialization for compatibility with GCC < 4.4.6 */ 23 .reserved = { 0 }, 24 V4L2_INIT_BT_TIMINGS(16, MAX_WIDTH, 16, MAX_HEIGHT, 14000000, 775000000, 25 V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT | 26 V4L2_DV_BT_STD_CVT | V4L2_DV_BT_STD_GTF, 27 V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_INTERLACED) 28 }; 29 30 /* ------------------------------------------------------------------ 31 Basic structures 32 ------------------------------------------------------------------*/ 33 34 struct vivid_fmt vivid_formats[] = { 35 { 36 .fourcc = V4L2_PIX_FMT_YUYV, 37 .vdownsampling = { 1 }, 38 .bit_depth = { 16 }, 39 .color_enc = TGP_COLOR_ENC_YCBCR, 40 .planes = 1, 41 .buffers = 1, 42 .data_offset = { PLANE0_DATA_OFFSET }, 43 }, 44 { 45 .fourcc = V4L2_PIX_FMT_UYVY, 46 .vdownsampling = { 1 }, 47 .bit_depth = { 16 }, 48 .color_enc = TGP_COLOR_ENC_YCBCR, 49 .planes = 1, 50 .buffers = 1, 51 }, 52 { 53 .fourcc = V4L2_PIX_FMT_YVYU, 54 .vdownsampling = { 1 }, 55 .bit_depth = { 16 }, 56 .color_enc = TGP_COLOR_ENC_YCBCR, 57 .planes = 1, 58 .buffers = 1, 59 }, 60 { 61 .fourcc = V4L2_PIX_FMT_VYUY, 62 .vdownsampling = { 1 }, 63 .bit_depth = { 16 }, 64 .color_enc = TGP_COLOR_ENC_YCBCR, 65 .planes = 1, 66 .buffers = 1, 67 }, 68 { 69 .fourcc = V4L2_PIX_FMT_YUV422P, 70 .vdownsampling = { 1, 1, 1 }, 71 .bit_depth = { 8, 4, 4 }, 72 .color_enc = TGP_COLOR_ENC_YCBCR, 73 .planes = 3, 74 .buffers = 1, 75 }, 76 { 77 .fourcc = V4L2_PIX_FMT_YUV420, 78 .vdownsampling = { 1, 2, 2 }, 79 .bit_depth = { 8, 4, 4 }, 80 .color_enc = TGP_COLOR_ENC_YCBCR, 81 .planes = 3, 82 .buffers = 1, 83 }, 84 { 85 .fourcc = V4L2_PIX_FMT_YVU420, 86 .vdownsampling = { 1, 2, 2 }, 87 .bit_depth = { 8, 4, 4 }, 88 .color_enc = TGP_COLOR_ENC_YCBCR, 89 .planes = 3, 90 .buffers = 1, 91 }, 92 { 93 .fourcc = V4L2_PIX_FMT_NV12, 94 .vdownsampling = { 1, 2 }, 95 .bit_depth = { 8, 8 }, 96 .color_enc = TGP_COLOR_ENC_YCBCR, 97 .planes = 2, 98 .buffers = 1, 99 }, 100 { 101 .fourcc = V4L2_PIX_FMT_NV21, 102 .vdownsampling = { 1, 2 }, 103 .bit_depth = { 8, 8 }, 104 .color_enc = TGP_COLOR_ENC_YCBCR, 105 .planes = 2, 106 .buffers = 1, 107 }, 108 { 109 .fourcc = V4L2_PIX_FMT_NV16, 110 .vdownsampling = { 1, 1 }, 111 .bit_depth = { 8, 8 }, 112 .color_enc = TGP_COLOR_ENC_YCBCR, 113 .planes = 2, 114 .buffers = 1, 115 }, 116 { 117 .fourcc = V4L2_PIX_FMT_NV61, 118 .vdownsampling = { 1, 1 }, 119 .bit_depth = { 8, 8 }, 120 .color_enc = TGP_COLOR_ENC_YCBCR, 121 .planes = 2, 122 .buffers = 1, 123 }, 124 { 125 .fourcc = V4L2_PIX_FMT_NV24, 126 .vdownsampling = { 1, 1 }, 127 .bit_depth = { 8, 16 }, 128 .color_enc = TGP_COLOR_ENC_YCBCR, 129 .planes = 2, 130 .buffers = 1, 131 }, 132 { 133 .fourcc = V4L2_PIX_FMT_NV42, 134 .vdownsampling = { 1, 1 }, 135 .bit_depth = { 8, 16 }, 136 .color_enc = TGP_COLOR_ENC_YCBCR, 137 .planes = 2, 138 .buffers = 1, 139 }, 140 { 141 .fourcc = V4L2_PIX_FMT_YUV555, /* uuuvvvvv ayyyyyuu */ 142 .vdownsampling = { 1 }, 143 .bit_depth = { 16 }, 144 .planes = 1, 145 .buffers = 1, 146 .alpha_mask = 0x8000, 147 }, 148 { 149 .fourcc = V4L2_PIX_FMT_YUV565, /* uuuvvvvv yyyyyuuu */ 150 .vdownsampling = { 1 }, 151 .bit_depth = { 16 }, 152 .planes = 1, 153 .buffers = 1, 154 }, 155 { 156 .fourcc = V4L2_PIX_FMT_YUV444, /* uuuuvvvv aaaayyyy */ 157 .vdownsampling = { 1 }, 158 .bit_depth = { 16 }, 159 .planes = 1, 160 .buffers = 1, 161 .alpha_mask = 0xf000, 162 }, 163 { 164 .fourcc = V4L2_PIX_FMT_YUV32, /* ayuv */ 165 .vdownsampling = { 1 }, 166 .bit_depth = { 32 }, 167 .planes = 1, 168 .buffers = 1, 169 .alpha_mask = 0x000000ff, 170 }, 171 { 172 .fourcc = V4L2_PIX_FMT_AYUV32, 173 .vdownsampling = { 1 }, 174 .bit_depth = { 32 }, 175 .planes = 1, 176 .buffers = 1, 177 .alpha_mask = 0x000000ff, 178 }, 179 { 180 .fourcc = V4L2_PIX_FMT_XYUV32, 181 .vdownsampling = { 1 }, 182 .bit_depth = { 32 }, 183 .planes = 1, 184 .buffers = 1, 185 }, 186 { 187 .fourcc = V4L2_PIX_FMT_VUYA32, 188 .vdownsampling = { 1 }, 189 .bit_depth = { 32 }, 190 .planes = 1, 191 .buffers = 1, 192 .alpha_mask = 0xff000000, 193 }, 194 { 195 .fourcc = V4L2_PIX_FMT_VUYX32, 196 .vdownsampling = { 1 }, 197 .bit_depth = { 32 }, 198 .planes = 1, 199 .buffers = 1, 200 }, 201 { 202 .fourcc = V4L2_PIX_FMT_YUVA32, 203 .vdownsampling = { 1 }, 204 .bit_depth = { 32 }, 205 .planes = 1, 206 .buffers = 1, 207 .alpha_mask = 0xff000000, 208 }, 209 { 210 .fourcc = V4L2_PIX_FMT_YUVX32, 211 .vdownsampling = { 1 }, 212 .bit_depth = { 32 }, 213 .planes = 1, 214 .buffers = 1, 215 }, 216 { 217 .fourcc = V4L2_PIX_FMT_GREY, 218 .vdownsampling = { 1 }, 219 .bit_depth = { 8 }, 220 .color_enc = TGP_COLOR_ENC_LUMA, 221 .planes = 1, 222 .buffers = 1, 223 }, 224 { 225 .fourcc = V4L2_PIX_FMT_Y10, 226 .vdownsampling = { 1 }, 227 .bit_depth = { 16 }, 228 .color_enc = TGP_COLOR_ENC_LUMA, 229 .planes = 1, 230 .buffers = 1, 231 }, 232 { 233 .fourcc = V4L2_PIX_FMT_Y12, 234 .vdownsampling = { 1 }, 235 .bit_depth = { 16 }, 236 .color_enc = TGP_COLOR_ENC_LUMA, 237 .planes = 1, 238 .buffers = 1, 239 }, 240 { 241 .fourcc = V4L2_PIX_FMT_Y16, 242 .vdownsampling = { 1 }, 243 .bit_depth = { 16 }, 244 .color_enc = TGP_COLOR_ENC_LUMA, 245 .planes = 1, 246 .buffers = 1, 247 }, 248 { 249 .fourcc = V4L2_PIX_FMT_Y16_BE, 250 .vdownsampling = { 1 }, 251 .bit_depth = { 16 }, 252 .color_enc = TGP_COLOR_ENC_LUMA, 253 .planes = 1, 254 .buffers = 1, 255 }, 256 { 257 .fourcc = V4L2_PIX_FMT_RGB332, /* rrrgggbb */ 258 .vdownsampling = { 1 }, 259 .bit_depth = { 8 }, 260 .planes = 1, 261 .buffers = 1, 262 }, 263 { 264 .fourcc = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */ 265 .vdownsampling = { 1 }, 266 .bit_depth = { 16 }, 267 .planes = 1, 268 .buffers = 1, 269 .can_do_overlay = true, 270 }, 271 { 272 .fourcc = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */ 273 .vdownsampling = { 1 }, 274 .bit_depth = { 16 }, 275 .planes = 1, 276 .buffers = 1, 277 .can_do_overlay = true, 278 }, 279 { 280 .fourcc = V4L2_PIX_FMT_RGB444, /* ggggbbbb xxxxrrrr */ 281 .vdownsampling = { 1 }, 282 .bit_depth = { 16 }, 283 .planes = 1, 284 .buffers = 1, 285 }, 286 { 287 .fourcc = V4L2_PIX_FMT_XRGB444, /* ggggbbbb xxxxrrrr */ 288 .vdownsampling = { 1 }, 289 .bit_depth = { 16 }, 290 .planes = 1, 291 .buffers = 1, 292 }, 293 { 294 .fourcc = V4L2_PIX_FMT_ARGB444, /* ggggbbbb aaaarrrr */ 295 .vdownsampling = { 1 }, 296 .bit_depth = { 16 }, 297 .planes = 1, 298 .buffers = 1, 299 .alpha_mask = 0x00f0, 300 }, 301 { 302 .fourcc = V4L2_PIX_FMT_RGBX444, /* bbbbxxxx rrrrgggg */ 303 .vdownsampling = { 1 }, 304 .bit_depth = { 16 }, 305 .planes = 1, 306 .buffers = 1, 307 }, 308 { 309 .fourcc = V4L2_PIX_FMT_RGBA444, /* bbbbaaaa rrrrgggg */ 310 .vdownsampling = { 1 }, 311 .bit_depth = { 16 }, 312 .planes = 1, 313 .buffers = 1, 314 .alpha_mask = 0x00f0, 315 }, 316 { 317 .fourcc = V4L2_PIX_FMT_XBGR444, /* ggggrrrr xxxxbbbb */ 318 .vdownsampling = { 1 }, 319 .bit_depth = { 16 }, 320 .planes = 1, 321 .buffers = 1, 322 }, 323 { 324 .fourcc = V4L2_PIX_FMT_ABGR444, /* ggggrrrr aaaabbbb */ 325 .vdownsampling = { 1 }, 326 .bit_depth = { 16 }, 327 .planes = 1, 328 .buffers = 1, 329 .alpha_mask = 0x00f0, 330 }, 331 { 332 .fourcc = V4L2_PIX_FMT_BGRX444, /* rrrrxxxx bbbbgggg */ 333 .vdownsampling = { 1 }, 334 .bit_depth = { 16 }, 335 .planes = 1, 336 .buffers = 1, 337 }, 338 { 339 .fourcc = V4L2_PIX_FMT_BGRA444, /* rrrraaaa bbbbgggg */ 340 .vdownsampling = { 1 }, 341 .bit_depth = { 16 }, 342 .planes = 1, 343 .buffers = 1, 344 .alpha_mask = 0x00f0, 345 }, 346 { 347 .fourcc = V4L2_PIX_FMT_RGB555, /* gggbbbbb xrrrrrgg */ 348 .vdownsampling = { 1 }, 349 .bit_depth = { 16 }, 350 .planes = 1, 351 .buffers = 1, 352 .can_do_overlay = true, 353 }, 354 { 355 .fourcc = V4L2_PIX_FMT_XRGB555, /* gggbbbbb xrrrrrgg */ 356 .vdownsampling = { 1 }, 357 .bit_depth = { 16 }, 358 .planes = 1, 359 .buffers = 1, 360 .can_do_overlay = true, 361 }, 362 { 363 .fourcc = V4L2_PIX_FMT_ARGB555, /* gggbbbbb arrrrrgg */ 364 .vdownsampling = { 1 }, 365 .bit_depth = { 16 }, 366 .planes = 1, 367 .buffers = 1, 368 .can_do_overlay = true, 369 .alpha_mask = 0x8000, 370 }, 371 { 372 .fourcc = V4L2_PIX_FMT_RGBX555, /* ggbbbbbx rrrrrggg */ 373 .vdownsampling = { 1 }, 374 .bit_depth = { 16 }, 375 .planes = 1, 376 .buffers = 1, 377 .can_do_overlay = true, 378 }, 379 { 380 .fourcc = V4L2_PIX_FMT_RGBA555, /* ggbbbbba rrrrrggg */ 381 .vdownsampling = { 1 }, 382 .bit_depth = { 16 }, 383 .planes = 1, 384 .buffers = 1, 385 .can_do_overlay = true, 386 .alpha_mask = 0x8000, 387 }, 388 { 389 .fourcc = V4L2_PIX_FMT_XBGR555, /* gggrrrrr xbbbbbgg */ 390 .vdownsampling = { 1 }, 391 .bit_depth = { 16 }, 392 .planes = 1, 393 .buffers = 1, 394 .can_do_overlay = true, 395 }, 396 { 397 .fourcc = V4L2_PIX_FMT_ABGR555, /* gggrrrrr abbbbbgg */ 398 .vdownsampling = { 1 }, 399 .bit_depth = { 16 }, 400 .planes = 1, 401 .buffers = 1, 402 .can_do_overlay = true, 403 .alpha_mask = 0x8000, 404 }, 405 { 406 .fourcc = V4L2_PIX_FMT_BGRX555, /* ggrrrrrx bbbbbggg */ 407 .vdownsampling = { 1 }, 408 .bit_depth = { 16 }, 409 .planes = 1, 410 .buffers = 1, 411 .can_do_overlay = true, 412 }, 413 { 414 .fourcc = V4L2_PIX_FMT_BGRA555, /* ggrrrrra bbbbbggg */ 415 .vdownsampling = { 1 }, 416 .bit_depth = { 16 }, 417 .planes = 1, 418 .buffers = 1, 419 .can_do_overlay = true, 420 .alpha_mask = 0x8000, 421 }, 422 { 423 .fourcc = V4L2_PIX_FMT_RGB555X, /* xrrrrrgg gggbbbbb */ 424 .vdownsampling = { 1 }, 425 .bit_depth = { 16 }, 426 .planes = 1, 427 .buffers = 1, 428 }, 429 { 430 .fourcc = V4L2_PIX_FMT_XRGB555X, /* xrrrrrgg gggbbbbb */ 431 .vdownsampling = { 1 }, 432 .bit_depth = { 16 }, 433 .planes = 1, 434 .buffers = 1, 435 }, 436 { 437 .fourcc = V4L2_PIX_FMT_ARGB555X, /* arrrrrgg gggbbbbb */ 438 .vdownsampling = { 1 }, 439 .bit_depth = { 16 }, 440 .planes = 1, 441 .buffers = 1, 442 .alpha_mask = 0x0080, 443 }, 444 { 445 .fourcc = V4L2_PIX_FMT_RGB24, /* rgb */ 446 .vdownsampling = { 1 }, 447 .bit_depth = { 24 }, 448 .planes = 1, 449 .buffers = 1, 450 }, 451 { 452 .fourcc = V4L2_PIX_FMT_BGR24, /* bgr */ 453 .vdownsampling = { 1 }, 454 .bit_depth = { 24 }, 455 .planes = 1, 456 .buffers = 1, 457 }, 458 { 459 .fourcc = V4L2_PIX_FMT_BGR666, /* bbbbbbgg ggggrrrr rrxxxxxx */ 460 .vdownsampling = { 1 }, 461 .bit_depth = { 32 }, 462 .planes = 1, 463 .buffers = 1, 464 }, 465 { 466 .fourcc = V4L2_PIX_FMT_RGB32, /* xrgb */ 467 .vdownsampling = { 1 }, 468 .bit_depth = { 32 }, 469 .planes = 1, 470 .buffers = 1, 471 }, 472 { 473 .fourcc = V4L2_PIX_FMT_BGR32, /* bgrx */ 474 .vdownsampling = { 1 }, 475 .bit_depth = { 32 }, 476 .planes = 1, 477 .buffers = 1, 478 }, 479 { 480 .fourcc = V4L2_PIX_FMT_XRGB32, /* xrgb */ 481 .vdownsampling = { 1 }, 482 .bit_depth = { 32 }, 483 .planes = 1, 484 .buffers = 1, 485 }, 486 { 487 .fourcc = V4L2_PIX_FMT_XBGR32, /* bgrx */ 488 .vdownsampling = { 1 }, 489 .bit_depth = { 32 }, 490 .planes = 1, 491 .buffers = 1, 492 }, 493 { 494 .fourcc = V4L2_PIX_FMT_ARGB32, /* argb */ 495 .vdownsampling = { 1 }, 496 .bit_depth = { 32 }, 497 .planes = 1, 498 .buffers = 1, 499 .alpha_mask = 0x000000ff, 500 }, 501 { 502 .fourcc = V4L2_PIX_FMT_ABGR32, /* bgra */ 503 .vdownsampling = { 1 }, 504 .bit_depth = { 32 }, 505 .planes = 1, 506 .buffers = 1, 507 .alpha_mask = 0xff000000, 508 }, 509 { 510 .fourcc = V4L2_PIX_FMT_RGBX32, /* rgbx */ 511 .vdownsampling = { 1 }, 512 .bit_depth = { 32 }, 513 .planes = 1, 514 .buffers = 1, 515 }, 516 { 517 .fourcc = V4L2_PIX_FMT_BGRX32, /* xbgr */ 518 .vdownsampling = { 1 }, 519 .bit_depth = { 32 }, 520 .planes = 1, 521 .buffers = 1, 522 }, 523 { 524 .fourcc = V4L2_PIX_FMT_RGBA32, /* rgba */ 525 .vdownsampling = { 1 }, 526 .bit_depth = { 32 }, 527 .planes = 1, 528 .buffers = 1, 529 .alpha_mask = 0x000000ff, 530 }, 531 { 532 .fourcc = V4L2_PIX_FMT_BGRA32, /* abgr */ 533 .vdownsampling = { 1 }, 534 .bit_depth = { 32 }, 535 .planes = 1, 536 .buffers = 1, 537 .alpha_mask = 0xff000000, 538 }, 539 { 540 .fourcc = V4L2_PIX_FMT_SBGGR8, /* Bayer BG/GR */ 541 .vdownsampling = { 1 }, 542 .bit_depth = { 8 }, 543 .planes = 1, 544 .buffers = 1, 545 }, 546 { 547 .fourcc = V4L2_PIX_FMT_SGBRG8, /* Bayer GB/RG */ 548 .vdownsampling = { 1 }, 549 .bit_depth = { 8 }, 550 .planes = 1, 551 .buffers = 1, 552 }, 553 { 554 .fourcc = V4L2_PIX_FMT_SGRBG8, /* Bayer GR/BG */ 555 .vdownsampling = { 1 }, 556 .bit_depth = { 8 }, 557 .planes = 1, 558 .buffers = 1, 559 }, 560 { 561 .fourcc = V4L2_PIX_FMT_SRGGB8, /* Bayer RG/GB */ 562 .vdownsampling = { 1 }, 563 .bit_depth = { 8 }, 564 .planes = 1, 565 .buffers = 1, 566 }, 567 { 568 .fourcc = V4L2_PIX_FMT_SBGGR10, /* Bayer BG/GR */ 569 .vdownsampling = { 1 }, 570 .bit_depth = { 16 }, 571 .planes = 1, 572 .buffers = 1, 573 }, 574 { 575 .fourcc = V4L2_PIX_FMT_SGBRG10, /* Bayer GB/RG */ 576 .vdownsampling = { 1 }, 577 .bit_depth = { 16 }, 578 .planes = 1, 579 .buffers = 1, 580 }, 581 { 582 .fourcc = V4L2_PIX_FMT_SGRBG10, /* Bayer GR/BG */ 583 .vdownsampling = { 1 }, 584 .bit_depth = { 16 }, 585 .planes = 1, 586 .buffers = 1, 587 }, 588 { 589 .fourcc = V4L2_PIX_FMT_SRGGB10, /* Bayer RG/GB */ 590 .vdownsampling = { 1 }, 591 .bit_depth = { 16 }, 592 .planes = 1, 593 .buffers = 1, 594 }, 595 { 596 .fourcc = V4L2_PIX_FMT_SBGGR12, /* Bayer BG/GR */ 597 .vdownsampling = { 1 }, 598 .bit_depth = { 16 }, 599 .planes = 1, 600 .buffers = 1, 601 }, 602 { 603 .fourcc = V4L2_PIX_FMT_SGBRG12, /* Bayer GB/RG */ 604 .vdownsampling = { 1 }, 605 .bit_depth = { 16 }, 606 .planes = 1, 607 .buffers = 1, 608 }, 609 { 610 .fourcc = V4L2_PIX_FMT_SGRBG12, /* Bayer GR/BG */ 611 .vdownsampling = { 1 }, 612 .bit_depth = { 16 }, 613 .planes = 1, 614 .buffers = 1, 615 }, 616 { 617 .fourcc = V4L2_PIX_FMT_SRGGB12, /* Bayer RG/GB */ 618 .vdownsampling = { 1 }, 619 .bit_depth = { 16 }, 620 .planes = 1, 621 .buffers = 1, 622 }, 623 { 624 .fourcc = V4L2_PIX_FMT_SBGGR16, /* Bayer BG/GR */ 625 .vdownsampling = { 1 }, 626 .bit_depth = { 16 }, 627 .planes = 1, 628 .buffers = 1, 629 }, 630 { 631 .fourcc = V4L2_PIX_FMT_SGBRG16, /* Bayer GB/RG */ 632 .vdownsampling = { 1 }, 633 .bit_depth = { 16 }, 634 .planes = 1, 635 .buffers = 1, 636 }, 637 { 638 .fourcc = V4L2_PIX_FMT_SGRBG16, /* Bayer GR/BG */ 639 .vdownsampling = { 1 }, 640 .bit_depth = { 16 }, 641 .planes = 1, 642 .buffers = 1, 643 }, 644 { 645 .fourcc = V4L2_PIX_FMT_SRGGB16, /* Bayer RG/GB */ 646 .vdownsampling = { 1 }, 647 .bit_depth = { 16 }, 648 .planes = 1, 649 .buffers = 1, 650 }, 651 { 652 .fourcc = V4L2_PIX_FMT_HSV24, /* HSV 24bits */ 653 .color_enc = TGP_COLOR_ENC_HSV, 654 .vdownsampling = { 1 }, 655 .bit_depth = { 24 }, 656 .planes = 1, 657 .buffers = 1, 658 }, 659 { 660 .fourcc = V4L2_PIX_FMT_HSV32, /* HSV 32bits */ 661 .color_enc = TGP_COLOR_ENC_HSV, 662 .vdownsampling = { 1 }, 663 .bit_depth = { 32 }, 664 .planes = 1, 665 .buffers = 1, 666 }, 667 668 /* Multiplanar formats */ 669 670 { 671 .fourcc = V4L2_PIX_FMT_NV16M, 672 .vdownsampling = { 1, 1 }, 673 .bit_depth = { 8, 8 }, 674 .color_enc = TGP_COLOR_ENC_YCBCR, 675 .planes = 2, 676 .buffers = 2, 677 .data_offset = { PLANE0_DATA_OFFSET, 0 }, 678 }, 679 { 680 .fourcc = V4L2_PIX_FMT_NV61M, 681 .vdownsampling = { 1, 1 }, 682 .bit_depth = { 8, 8 }, 683 .color_enc = TGP_COLOR_ENC_YCBCR, 684 .planes = 2, 685 .buffers = 2, 686 .data_offset = { 0, PLANE0_DATA_OFFSET }, 687 }, 688 { 689 .fourcc = V4L2_PIX_FMT_YUV420M, 690 .vdownsampling = { 1, 2, 2 }, 691 .bit_depth = { 8, 4, 4 }, 692 .color_enc = TGP_COLOR_ENC_YCBCR, 693 .planes = 3, 694 .buffers = 3, 695 }, 696 { 697 .fourcc = V4L2_PIX_FMT_YVU420M, 698 .vdownsampling = { 1, 2, 2 }, 699 .bit_depth = { 8, 4, 4 }, 700 .color_enc = TGP_COLOR_ENC_YCBCR, 701 .planes = 3, 702 .buffers = 3, 703 }, 704 { 705 .fourcc = V4L2_PIX_FMT_NV12M, 706 .vdownsampling = { 1, 2 }, 707 .bit_depth = { 8, 8 }, 708 .color_enc = TGP_COLOR_ENC_YCBCR, 709 .planes = 2, 710 .buffers = 2, 711 }, 712 { 713 .fourcc = V4L2_PIX_FMT_NV21M, 714 .vdownsampling = { 1, 2 }, 715 .bit_depth = { 8, 8 }, 716 .color_enc = TGP_COLOR_ENC_YCBCR, 717 .planes = 2, 718 .buffers = 2, 719 }, 720 { 721 .fourcc = V4L2_PIX_FMT_YUV422M, 722 .vdownsampling = { 1, 1, 1 }, 723 .bit_depth = { 8, 4, 4 }, 724 .color_enc = TGP_COLOR_ENC_YCBCR, 725 .planes = 3, 726 .buffers = 3, 727 }, 728 { 729 .fourcc = V4L2_PIX_FMT_YVU422M, 730 .vdownsampling = { 1, 1, 1 }, 731 .bit_depth = { 8, 4, 4 }, 732 .color_enc = TGP_COLOR_ENC_YCBCR, 733 .planes = 3, 734 .buffers = 3, 735 }, 736 { 737 .fourcc = V4L2_PIX_FMT_YUV444M, 738 .vdownsampling = { 1, 1, 1 }, 739 .bit_depth = { 8, 8, 8 }, 740 .color_enc = TGP_COLOR_ENC_YCBCR, 741 .planes = 3, 742 .buffers = 3, 743 }, 744 { 745 .fourcc = V4L2_PIX_FMT_YVU444M, 746 .vdownsampling = { 1, 1, 1 }, 747 .bit_depth = { 8, 8, 8 }, 748 .color_enc = TGP_COLOR_ENC_YCBCR, 749 .planes = 3, 750 .buffers = 3, 751 }, 752 }; 753 754 /* There are this many multiplanar formats in the list */ 755 #define VIVID_MPLANAR_FORMATS 10 756 757 const struct vivid_fmt *vivid_get_format(struct vivid_dev *dev, u32 pixelformat) 758 { 759 const struct vivid_fmt *fmt; 760 unsigned k; 761 762 for (k = 0; k < ARRAY_SIZE(vivid_formats); k++) { 763 fmt = &vivid_formats[k]; 764 if (fmt->fourcc == pixelformat) 765 if (fmt->buffers == 1 || dev->multiplanar) 766 return fmt; 767 } 768 769 return NULL; 770 } 771 772 struct vivid_dev *vivid_output_is_connected_to(struct vivid_dev *dev) 773 { 774 struct vivid_dev *input_inst = dev->output_to_input_instance[dev->output]; 775 776 if (!input_inst) 777 return NULL; 778 if (input_inst->input != dev->output_to_input_index[dev->output]) 779 return NULL; 780 return input_inst; 781 } 782 783 struct vivid_dev *vivid_input_is_connected_to(struct vivid_dev *dev) 784 { 785 s32 connected_output = dev->input_is_connected_to_output[dev->input]; 786 787 if (connected_output < FIXED_MENU_ITEMS) 788 return NULL; 789 struct vivid_dev *output_inst = NULL; 790 791 if (vivid_is_hdmi_cap(dev)) { 792 output_inst = vivid_ctrl_hdmi_to_output_instance[connected_output]; 793 if (vivid_ctrl_hdmi_to_output_index[connected_output] != output_inst->output) 794 return NULL; 795 return output_inst; 796 } else if (vivid_is_svid_cap(dev)) { 797 output_inst = vivid_ctrl_svid_to_output_instance[connected_output]; 798 if (vivid_ctrl_svid_to_output_index[connected_output] != output_inst->output) 799 return NULL; 800 return output_inst; 801 } else { 802 return NULL; 803 } 804 return output_inst; 805 } 806 807 bool vivid_vid_can_loop(struct vivid_dev *dev) 808 { 809 struct vivid_dev *output_inst = vivid_input_is_connected_to(dev); 810 811 if (!output_inst) 812 return false; 813 if (!vb2_is_streaming(&output_inst->vb_vid_out_q)) 814 return false; 815 if (dev->src_rect.width != output_inst->sink_rect.width || 816 dev->src_rect.height != output_inst->sink_rect.height) 817 return false; 818 if (dev->fmt_cap->fourcc != output_inst->fmt_out->fourcc) 819 return false; 820 if (dev->field_cap != output_inst->field_out) 821 return false; 822 /* 823 * While this can be supported, it is just too much work 824 * to actually implement. 825 */ 826 if (dev->field_cap == V4L2_FIELD_SEQ_TB || 827 dev->field_cap == V4L2_FIELD_SEQ_BT) 828 return false; 829 if (vivid_is_hdmi_cap(dev)) 830 return true; 831 if (!(dev->std_cap[dev->input] & V4L2_STD_525_60) != 832 !(output_inst->std_out & V4L2_STD_525_60)) 833 return false; 834 return true; 835 } 836 837 void vivid_send_input_source_change(struct vivid_dev *dev, unsigned int input_index) 838 { 839 struct v4l2_event ev = { 840 .type = V4L2_EVENT_SOURCE_CHANGE, 841 .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION, 842 }; 843 ev.id = input_index; 844 845 if (video_is_registered(&dev->vid_cap_dev) && dev->has_vid_cap) 846 v4l2_event_queue(&dev->vid_cap_dev, &ev); 847 if (dev->input_type[input_index] == TV || dev->input_type[input_index] == SVID) 848 if (video_is_registered(&dev->vbi_cap_dev) && dev->has_vbi_cap) 849 v4l2_event_queue(&dev->vbi_cap_dev, &ev); 850 } 851 852 void vivid_send_source_change(struct vivid_dev *dev, unsigned int type) 853 { 854 for (int i = 0; i < dev->num_inputs; i++) 855 if (dev->input_type[i] == type) 856 vivid_send_input_source_change(dev, i); 857 } 858 859 /* 860 * Conversion function that converts a single-planar format to a 861 * single-plane multiplanar format. 862 */ 863 void fmt_sp2mp(const struct v4l2_format *sp_fmt, struct v4l2_format *mp_fmt) 864 { 865 struct v4l2_pix_format_mplane *mp = &mp_fmt->fmt.pix_mp; 866 struct v4l2_plane_pix_format *ppix = &mp->plane_fmt[0]; 867 const struct v4l2_pix_format *pix = &sp_fmt->fmt.pix; 868 bool is_out = sp_fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT; 869 870 memset(mp->reserved, 0, sizeof(mp->reserved)); 871 mp_fmt->type = is_out ? V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE : 872 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 873 mp->width = pix->width; 874 mp->height = pix->height; 875 mp->pixelformat = pix->pixelformat; 876 mp->field = pix->field; 877 mp->colorspace = pix->colorspace; 878 mp->xfer_func = pix->xfer_func; 879 /* Also copies hsv_enc */ 880 mp->ycbcr_enc = pix->ycbcr_enc; 881 mp->quantization = pix->quantization; 882 mp->num_planes = 1; 883 mp->flags = pix->flags; 884 ppix->sizeimage = pix->sizeimage; 885 ppix->bytesperline = pix->bytesperline; 886 memset(ppix->reserved, 0, sizeof(ppix->reserved)); 887 } 888 889 int fmt_sp2mp_func(struct file *file, void *priv, 890 struct v4l2_format *f, fmtfunc func) 891 { 892 struct v4l2_format fmt; 893 struct v4l2_pix_format_mplane *mp = &fmt.fmt.pix_mp; 894 struct v4l2_plane_pix_format *ppix = &mp->plane_fmt[0]; 895 struct v4l2_pix_format *pix = &f->fmt.pix; 896 int ret; 897 898 /* Converts to a mplane format */ 899 fmt_sp2mp(f, &fmt); 900 /* Passes it to the generic mplane format function */ 901 ret = func(file, priv, &fmt); 902 /* Copies back the mplane data to the single plane format */ 903 pix->width = mp->width; 904 pix->height = mp->height; 905 pix->pixelformat = mp->pixelformat; 906 pix->field = mp->field; 907 pix->colorspace = mp->colorspace; 908 pix->xfer_func = mp->xfer_func; 909 /* Also copies hsv_enc */ 910 pix->ycbcr_enc = mp->ycbcr_enc; 911 pix->quantization = mp->quantization; 912 pix->sizeimage = ppix->sizeimage; 913 pix->bytesperline = ppix->bytesperline; 914 pix->flags = mp->flags; 915 return ret; 916 } 917 918 int vivid_vid_adjust_sel(unsigned flags, struct v4l2_rect *r) 919 { 920 unsigned w = r->width; 921 unsigned h = r->height; 922 923 /* sanitize w and h in case someone passes ~0 as the value */ 924 w &= 0xffff; 925 h &= 0xffff; 926 if (!(flags & V4L2_SEL_FLAG_LE)) { 927 w++; 928 h++; 929 if (w < 2) 930 w = 2; 931 if (h < 2) 932 h = 2; 933 } 934 if (!(flags & V4L2_SEL_FLAG_GE)) { 935 if (w > MAX_WIDTH) 936 w = MAX_WIDTH; 937 if (h > MAX_HEIGHT) 938 h = MAX_HEIGHT; 939 } 940 w = w & ~1; 941 h = h & ~1; 942 if (w < 2 || h < 2) 943 return -ERANGE; 944 if (w > MAX_WIDTH || h > MAX_HEIGHT) 945 return -ERANGE; 946 if (r->top < 0) 947 r->top = 0; 948 if (r->left < 0) 949 r->left = 0; 950 /* sanitize left and top in case someone passes ~0 as the value */ 951 r->left &= 0xfffe; 952 r->top &= 0xfffe; 953 if (r->left + w > MAX_WIDTH) 954 r->left = MAX_WIDTH - w; 955 if (r->top + h > MAX_HEIGHT) 956 r->top = MAX_HEIGHT - h; 957 if ((flags & (V4L2_SEL_FLAG_GE | V4L2_SEL_FLAG_LE)) == 958 (V4L2_SEL_FLAG_GE | V4L2_SEL_FLAG_LE) && 959 (r->width != w || r->height != h)) 960 return -ERANGE; 961 r->width = w; 962 r->height = h; 963 return 0; 964 } 965 966 int vivid_enum_fmt_vid(struct file *file, void *priv, 967 struct v4l2_fmtdesc *f) 968 { 969 struct vivid_dev *dev = video_drvdata(file); 970 const struct vivid_fmt *fmt; 971 972 if (f->index >= ARRAY_SIZE(vivid_formats) - 973 (dev->multiplanar ? 0 : VIVID_MPLANAR_FORMATS)) 974 return -EINVAL; 975 976 fmt = &vivid_formats[f->index]; 977 978 f->pixelformat = fmt->fourcc; 979 980 if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && 981 f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) 982 return 0; 983 /* 984 * For capture devices, we support the CSC API. 985 * We allow userspace to: 986 * 1. set the colorspace 987 * 2. set the xfer_func 988 * 3. set the ycbcr_enc on YUV formats 989 * 4. set the hsv_enc on HSV formats 990 * 5. set the quantization on YUV and RGB formats 991 */ 992 f->flags |= V4L2_FMT_FLAG_CSC_COLORSPACE; 993 f->flags |= V4L2_FMT_FLAG_CSC_XFER_FUNC; 994 995 if (fmt->color_enc == TGP_COLOR_ENC_YCBCR) { 996 f->flags |= V4L2_FMT_FLAG_CSC_YCBCR_ENC; 997 f->flags |= V4L2_FMT_FLAG_CSC_QUANTIZATION; 998 } else if (fmt->color_enc == TGP_COLOR_ENC_HSV) { 999 f->flags |= V4L2_FMT_FLAG_CSC_HSV_ENC; 1000 } else if (fmt->color_enc == TGP_COLOR_ENC_RGB) { 1001 f->flags |= V4L2_FMT_FLAG_CSC_QUANTIZATION; 1002 } 1003 1004 return 0; 1005 } 1006 1007 int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id) 1008 { 1009 struct vivid_dev *dev = video_drvdata(file); 1010 struct video_device *vdev = video_devdata(file); 1011 1012 if (vdev->vfl_dir == VFL_DIR_RX) { 1013 if (!vivid_is_sdtv_cap(dev)) 1014 return -ENODATA; 1015 *id = dev->std_cap[dev->input]; 1016 } else { 1017 if (!vivid_is_svid_out(dev)) 1018 return -ENODATA; 1019 *id = dev->std_out; 1020 } 1021 return 0; 1022 } 1023 1024 int vidioc_g_dv_timings(struct file *file, void *_fh, 1025 struct v4l2_dv_timings *timings) 1026 { 1027 struct vivid_dev *dev = video_drvdata(file); 1028 struct video_device *vdev = video_devdata(file); 1029 1030 if (vdev->vfl_dir == VFL_DIR_RX) { 1031 if (!vivid_is_hdmi_cap(dev)) 1032 return -ENODATA; 1033 *timings = dev->dv_timings_cap[dev->input]; 1034 } else { 1035 if (!vivid_is_hdmi_out(dev)) 1036 return -ENODATA; 1037 *timings = dev->dv_timings_out; 1038 } 1039 return 0; 1040 } 1041 1042 int vidioc_enum_dv_timings(struct file *file, void *_fh, 1043 struct v4l2_enum_dv_timings *timings) 1044 { 1045 struct vivid_dev *dev = video_drvdata(file); 1046 struct video_device *vdev = video_devdata(file); 1047 1048 if (vdev->vfl_dir == VFL_DIR_RX) { 1049 if (!vivid_is_hdmi_cap(dev)) 1050 return -ENODATA; 1051 } else { 1052 if (!vivid_is_hdmi_out(dev)) 1053 return -ENODATA; 1054 } 1055 return v4l2_enum_dv_timings_cap(timings, &vivid_dv_timings_cap, 1056 NULL, NULL); 1057 } 1058 1059 int vidioc_dv_timings_cap(struct file *file, void *_fh, 1060 struct v4l2_dv_timings_cap *cap) 1061 { 1062 struct vivid_dev *dev = video_drvdata(file); 1063 struct video_device *vdev = video_devdata(file); 1064 1065 if (vdev->vfl_dir == VFL_DIR_RX) { 1066 if (!vivid_is_hdmi_cap(dev)) 1067 return -ENODATA; 1068 } else { 1069 if (!vivid_is_hdmi_out(dev)) 1070 return -ENODATA; 1071 } 1072 *cap = vivid_dv_timings_cap; 1073 return 0; 1074 } 1075 1076 int vidioc_g_edid(struct file *file, void *_fh, 1077 struct v4l2_edid *edid) 1078 { 1079 struct vivid_dev *dev = video_drvdata(file); 1080 struct vivid_dev *dev_rx = dev; 1081 struct video_device *vdev = video_devdata(file); 1082 struct cec_adapter *adap; 1083 unsigned int loc; 1084 1085 memset(edid->reserved, 0, sizeof(edid->reserved)); 1086 if (vdev->vfl_dir == VFL_DIR_RX) { 1087 if (edid->pad >= dev->num_inputs) 1088 return -EINVAL; 1089 if (dev->input_type[edid->pad] != HDMI) 1090 return -EINVAL; 1091 adap = dev->cec_rx_adap; 1092 } else { 1093 if (edid->pad >= dev->num_outputs) 1094 return -EINVAL; 1095 if (dev->output_type[edid->pad] != HDMI) 1096 return -EINVAL; 1097 dev_rx = dev->output_to_input_instance[edid->pad]; 1098 if (!dev_rx) 1099 return -ENODATA; 1100 1101 unsigned int hdmi_output = dev->output_to_iface_index[edid->pad]; 1102 1103 adap = dev->cec_tx_adap[hdmi_output]; 1104 } 1105 if (edid->start_block == 0 && edid->blocks == 0) { 1106 edid->blocks = dev_rx->edid_blocks; 1107 return 0; 1108 } 1109 if (dev_rx->edid_blocks == 0) 1110 return -ENODATA; 1111 if (edid->start_block >= dev_rx->edid_blocks) 1112 return -EINVAL; 1113 if (edid->blocks > dev_rx->edid_blocks - edid->start_block) 1114 edid->blocks = dev_rx->edid_blocks - edid->start_block; 1115 1116 memcpy(edid->edid, dev_rx->edid + edid->start_block * 128, edid->blocks * 128); 1117 1118 loc = cec_get_edid_spa_location(dev_rx->edid, 1119 dev_rx->edid_blocks * 128); 1120 if (vdev->vfl_dir == VFL_DIR_TX && adap && loc && 1121 loc >= edid->start_block * 128 && 1122 loc < (edid->start_block + edid->blocks) * 128) { 1123 unsigned int i; 1124 u8 sum = 0; 1125 1126 loc -= edid->start_block * 128; 1127 edid->edid[loc] = adap->phys_addr >> 8; 1128 edid->edid[loc + 1] = adap->phys_addr & 0xff; 1129 loc &= ~0x7f; 1130 1131 /* update the checksum */ 1132 for (i = loc; i < loc + 127; i++) 1133 sum += edid->edid[i]; 1134 edid->edid[i] = 256 - sum; 1135 } 1136 return 0; 1137 } 1138