1138 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*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 20const 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 structures32 ------------------------------------------------------------------*/33 34struct 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 10756 757const 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 772struct 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 783struct 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 807bool 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 work824 * 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 837void 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 852void 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 a861 * single-plane multiplanar format.862 */863void 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 889int 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 918int 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 966int 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 colorspace987 * 2. set the xfer_func988 * 3. set the ycbcr_enc on YUV formats989 * 4. set the hsv_enc on HSV formats990 * 5. set the quantization on YUV and RGB formats991 */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 1007int 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 1024int 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 1042int 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 1059int 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 1076int 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