linux/drivers/media/platform/vivid/vivid-vid-common.c
<<
>>
Prefs
   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                .color_enc = TGP_COLOR_ENC_YCBCR,
  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                .color_enc = TGP_COLOR_ENC_YCBCR,
  61                .planes   = 1,
  62                .buffers = 1,
  63        },
  64        {
  65                .fourcc   = V4L2_PIX_FMT_YVYU,
  66                .vdownsampling = { 1 },
  67                .bit_depth = { 16 },
  68                .color_enc = TGP_COLOR_ENC_YCBCR,
  69                .planes   = 1,
  70                .buffers = 1,
  71        },
  72        {
  73                .fourcc   = V4L2_PIX_FMT_VYUY,
  74                .vdownsampling = { 1 },
  75                .bit_depth = { 16 },
  76                .color_enc = TGP_COLOR_ENC_YCBCR,
  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                .color_enc = TGP_COLOR_ENC_YCBCR,
  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                .color_enc = TGP_COLOR_ENC_YCBCR,
  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                .color_enc = TGP_COLOR_ENC_YCBCR,
 101                .planes   = 3,
 102                .buffers = 1,
 103        },
 104        {
 105                .fourcc   = V4L2_PIX_FMT_NV12,
 106                .vdownsampling = { 1, 2 },
 107                .bit_depth = { 8, 8 },
 108                .color_enc = TGP_COLOR_ENC_YCBCR,
 109                .planes   = 2,
 110                .buffers = 1,
 111        },
 112        {
 113                .fourcc   = V4L2_PIX_FMT_NV21,
 114                .vdownsampling = { 1, 2 },
 115                .bit_depth = { 8, 8 },
 116                .color_enc = TGP_COLOR_ENC_YCBCR,
 117                .planes   = 2,
 118                .buffers = 1,
 119        },
 120        {
 121                .fourcc   = V4L2_PIX_FMT_NV16,
 122                .vdownsampling = { 1, 1 },
 123                .bit_depth = { 8, 8 },
 124                .color_enc = TGP_COLOR_ENC_YCBCR,
 125                .planes   = 2,
 126                .buffers = 1,
 127        },
 128        {
 129                .fourcc   = V4L2_PIX_FMT_NV61,
 130                .vdownsampling = { 1, 1 },
 131                .bit_depth = { 8, 8 },
 132                .color_enc = TGP_COLOR_ENC_YCBCR,
 133                .planes   = 2,
 134                .buffers = 1,
 135        },
 136        {
 137                .fourcc   = V4L2_PIX_FMT_NV24,
 138                .vdownsampling = { 1, 1 },
 139                .bit_depth = { 8, 16 },
 140                .color_enc = TGP_COLOR_ENC_YCBCR,
 141                .planes   = 2,
 142                .buffers = 1,
 143        },
 144        {
 145                .fourcc   = V4L2_PIX_FMT_NV42,
 146                .vdownsampling = { 1, 1 },
 147                .bit_depth = { 8, 16 },
 148                .color_enc = TGP_COLOR_ENC_YCBCR,
 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                .color_enc = TGP_COLOR_ENC_LUMA,
 188                .planes   = 1,
 189                .buffers = 1,
 190        },
 191        {
 192                .fourcc   = V4L2_PIX_FMT_Y16,
 193                .vdownsampling = { 1 },
 194                .bit_depth = { 16 },
 195                .color_enc = TGP_COLOR_ENC_LUMA,
 196                .planes   = 1,
 197                .buffers = 1,
 198        },
 199        {
 200                .fourcc   = V4L2_PIX_FMT_Y16_BE,
 201                .vdownsampling = { 1 },
 202                .bit_depth = { 16 },
 203                .color_enc = TGP_COLOR_ENC_LUMA,
 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_SBGGR10, /* Bayer BG/GR */
 394                .vdownsampling = { 1 },
 395                .bit_depth = { 16 },
 396                .planes   = 1,
 397                .buffers = 1,
 398        },
 399        {
 400                .fourcc   = V4L2_PIX_FMT_SGBRG10, /* Bayer GB/RG */
 401                .vdownsampling = { 1 },
 402                .bit_depth = { 16 },
 403                .planes   = 1,
 404                .buffers = 1,
 405        },
 406        {
 407                .fourcc   = V4L2_PIX_FMT_SGRBG10, /* Bayer GR/BG */
 408                .vdownsampling = { 1 },
 409                .bit_depth = { 16 },
 410                .planes   = 1,
 411                .buffers = 1,
 412        },
 413        {
 414                .fourcc   = V4L2_PIX_FMT_SRGGB10, /* Bayer RG/GB */
 415                .vdownsampling = { 1 },
 416                .bit_depth = { 16 },
 417                .planes   = 1,
 418                .buffers = 1,
 419        },
 420        {
 421                .fourcc   = V4L2_PIX_FMT_SBGGR12, /* Bayer BG/GR */
 422                .vdownsampling = { 1 },
 423                .bit_depth = { 16 },
 424                .planes   = 1,
 425                .buffers = 1,
 426        },
 427        {
 428                .fourcc   = V4L2_PIX_FMT_SGBRG12, /* Bayer GB/RG */
 429                .vdownsampling = { 1 },
 430                .bit_depth = { 16 },
 431                .planes   = 1,
 432                .buffers = 1,
 433        },
 434        {
 435                .fourcc   = V4L2_PIX_FMT_SGRBG12, /* Bayer GR/BG */
 436                .vdownsampling = { 1 },
 437                .bit_depth = { 16 },
 438                .planes   = 1,
 439                .buffers = 1,
 440        },
 441        {
 442                .fourcc   = V4L2_PIX_FMT_SRGGB12, /* Bayer RG/GB */
 443                .vdownsampling = { 1 },
 444                .bit_depth = { 16 },
 445                .planes   = 1,
 446                .buffers = 1,
 447        },
 448        {
 449                .fourcc   = V4L2_PIX_FMT_HSV24, /* HSV 24bits */
 450                .color_enc = TGP_COLOR_ENC_HSV,
 451                .vdownsampling = { 1 },
 452                .bit_depth = { 24 },
 453                .planes   = 1,
 454                .buffers = 1,
 455        },
 456        {
 457                .fourcc   = V4L2_PIX_FMT_HSV32, /* HSV 32bits */
 458                .color_enc = TGP_COLOR_ENC_HSV,
 459                .vdownsampling = { 1 },
 460                .bit_depth = { 32 },
 461                .planes   = 1,
 462                .buffers = 1,
 463        },
 464
 465        /* Multiplanar formats */
 466
 467        {
 468                .fourcc   = V4L2_PIX_FMT_NV16M,
 469                .vdownsampling = { 1, 1 },
 470                .bit_depth = { 8, 8 },
 471                .color_enc = TGP_COLOR_ENC_YCBCR,
 472                .planes   = 2,
 473                .buffers = 2,
 474                .data_offset = { PLANE0_DATA_OFFSET, 0 },
 475        },
 476        {
 477                .fourcc   = V4L2_PIX_FMT_NV61M,
 478                .vdownsampling = { 1, 1 },
 479                .bit_depth = { 8, 8 },
 480                .color_enc = TGP_COLOR_ENC_YCBCR,
 481                .planes   = 2,
 482                .buffers = 2,
 483                .data_offset = { 0, PLANE0_DATA_OFFSET },
 484        },
 485        {
 486                .fourcc   = V4L2_PIX_FMT_YUV420M,
 487                .vdownsampling = { 1, 2, 2 },
 488                .bit_depth = { 8, 4, 4 },
 489                .color_enc = TGP_COLOR_ENC_YCBCR,
 490                .planes   = 3,
 491                .buffers = 3,
 492        },
 493        {
 494                .fourcc   = V4L2_PIX_FMT_YVU420M,
 495                .vdownsampling = { 1, 2, 2 },
 496                .bit_depth = { 8, 4, 4 },
 497                .color_enc = TGP_COLOR_ENC_YCBCR,
 498                .planes   = 3,
 499                .buffers = 3,
 500        },
 501        {
 502                .fourcc   = V4L2_PIX_FMT_NV12M,
 503                .vdownsampling = { 1, 2 },
 504                .bit_depth = { 8, 8 },
 505                .color_enc = TGP_COLOR_ENC_YCBCR,
 506                .planes   = 2,
 507                .buffers = 2,
 508        },
 509        {
 510                .fourcc   = V4L2_PIX_FMT_NV21M,
 511                .vdownsampling = { 1, 2 },
 512                .bit_depth = { 8, 8 },
 513                .color_enc = TGP_COLOR_ENC_YCBCR,
 514                .planes   = 2,
 515                .buffers = 2,
 516        },
 517        {
 518                .fourcc   = V4L2_PIX_FMT_YUV422M,
 519                .vdownsampling = { 1, 1, 1 },
 520                .bit_depth = { 8, 4, 4 },
 521                .color_enc = TGP_COLOR_ENC_YCBCR,
 522                .planes   = 3,
 523                .buffers = 3,
 524        },
 525        {
 526                .fourcc   = V4L2_PIX_FMT_YVU422M,
 527                .vdownsampling = { 1, 1, 1 },
 528                .bit_depth = { 8, 4, 4 },
 529                .color_enc = TGP_COLOR_ENC_YCBCR,
 530                .planes   = 3,
 531                .buffers = 3,
 532        },
 533        {
 534                .fourcc   = V4L2_PIX_FMT_YUV444M,
 535                .vdownsampling = { 1, 1, 1 },
 536                .bit_depth = { 8, 8, 8 },
 537                .color_enc = TGP_COLOR_ENC_YCBCR,
 538                .planes   = 3,
 539                .buffers = 3,
 540        },
 541        {
 542                .fourcc   = V4L2_PIX_FMT_YVU444M,
 543                .vdownsampling = { 1, 1, 1 },
 544                .bit_depth = { 8, 8, 8 },
 545                .color_enc = TGP_COLOR_ENC_YCBCR,
 546                .planes   = 3,
 547                .buffers = 3,
 548        },
 549};
 550
 551/* There are this many multiplanar formats in the list */
 552#define VIVID_MPLANAR_FORMATS 10
 553
 554const struct vivid_fmt *vivid_get_format(struct vivid_dev *dev, u32 pixelformat)
 555{
 556        const struct vivid_fmt *fmt;
 557        unsigned k;
 558
 559        for (k = 0; k < ARRAY_SIZE(vivid_formats); k++) {
 560                fmt = &vivid_formats[k];
 561                if (fmt->fourcc == pixelformat)
 562                        if (fmt->buffers == 1 || dev->multiplanar)
 563                                return fmt;
 564        }
 565
 566        return NULL;
 567}
 568
 569bool vivid_vid_can_loop(struct vivid_dev *dev)
 570{
 571        if (dev->src_rect.width != dev->sink_rect.width ||
 572            dev->src_rect.height != dev->sink_rect.height)
 573                return false;
 574        if (dev->fmt_cap->fourcc != dev->fmt_out->fourcc)
 575                return false;
 576        if (dev->field_cap != dev->field_out)
 577                return false;
 578        /*
 579         * While this can be supported, it is just too much work
 580         * to actually implement.
 581         */
 582        if (dev->field_cap == V4L2_FIELD_SEQ_TB ||
 583            dev->field_cap == V4L2_FIELD_SEQ_BT)
 584                return false;
 585        if (vivid_is_svid_cap(dev) && vivid_is_svid_out(dev)) {
 586                if (!(dev->std_cap & V4L2_STD_525_60) !=
 587                    !(dev->std_out & V4L2_STD_525_60))
 588                        return false;
 589                return true;
 590        }
 591        if (vivid_is_hdmi_cap(dev) && vivid_is_hdmi_out(dev))
 592                return true;
 593        return false;
 594}
 595
 596void vivid_send_source_change(struct vivid_dev *dev, unsigned type)
 597{
 598        struct v4l2_event ev = {
 599                .type = V4L2_EVENT_SOURCE_CHANGE,
 600                .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
 601        };
 602        unsigned i;
 603
 604        for (i = 0; i < dev->num_inputs; i++) {
 605                ev.id = i;
 606                if (dev->input_type[i] == type) {
 607                        if (video_is_registered(&dev->vid_cap_dev) && dev->has_vid_cap)
 608                                v4l2_event_queue(&dev->vid_cap_dev, &ev);
 609                        if (video_is_registered(&dev->vbi_cap_dev) && dev->has_vbi_cap)
 610                                v4l2_event_queue(&dev->vbi_cap_dev, &ev);
 611                }
 612        }
 613}
 614
 615/*
 616 * Conversion function that converts a single-planar format to a
 617 * single-plane multiplanar format.
 618 */
 619void fmt_sp2mp(const struct v4l2_format *sp_fmt, struct v4l2_format *mp_fmt)
 620{
 621        struct v4l2_pix_format_mplane *mp = &mp_fmt->fmt.pix_mp;
 622        struct v4l2_plane_pix_format *ppix = &mp->plane_fmt[0];
 623        const struct v4l2_pix_format *pix = &sp_fmt->fmt.pix;
 624        bool is_out = sp_fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT;
 625
 626        memset(mp->reserved, 0, sizeof(mp->reserved));
 627        mp_fmt->type = is_out ? V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE :
 628                           V4L2_CAP_VIDEO_CAPTURE_MPLANE;
 629        mp->width = pix->width;
 630        mp->height = pix->height;
 631        mp->pixelformat = pix->pixelformat;
 632        mp->field = pix->field;
 633        mp->colorspace = pix->colorspace;
 634        mp->xfer_func = pix->xfer_func;
 635        /* Also copies hsv_enc */
 636        mp->ycbcr_enc = pix->ycbcr_enc;
 637        mp->quantization = pix->quantization;
 638        mp->num_planes = 1;
 639        mp->flags = pix->flags;
 640        ppix->sizeimage = pix->sizeimage;
 641        ppix->bytesperline = pix->bytesperline;
 642        memset(ppix->reserved, 0, sizeof(ppix->reserved));
 643}
 644
 645int fmt_sp2mp_func(struct file *file, void *priv,
 646                struct v4l2_format *f, fmtfunc func)
 647{
 648        struct v4l2_format fmt;
 649        struct v4l2_pix_format_mplane *mp = &fmt.fmt.pix_mp;
 650        struct v4l2_plane_pix_format *ppix = &mp->plane_fmt[0];
 651        struct v4l2_pix_format *pix = &f->fmt.pix;
 652        int ret;
 653
 654        /* Converts to a mplane format */
 655        fmt_sp2mp(f, &fmt);
 656        /* Passes it to the generic mplane format function */
 657        ret = func(file, priv, &fmt);
 658        /* Copies back the mplane data to the single plane format */
 659        pix->width = mp->width;
 660        pix->height = mp->height;
 661        pix->pixelformat = mp->pixelformat;
 662        pix->field = mp->field;
 663        pix->colorspace = mp->colorspace;
 664        pix->xfer_func = mp->xfer_func;
 665        /* Also copies hsv_enc */
 666        pix->ycbcr_enc = mp->ycbcr_enc;
 667        pix->quantization = mp->quantization;
 668        pix->sizeimage = ppix->sizeimage;
 669        pix->bytesperline = ppix->bytesperline;
 670        pix->flags = mp->flags;
 671        return ret;
 672}
 673
 674int vivid_vid_adjust_sel(unsigned flags, struct v4l2_rect *r)
 675{
 676        unsigned w = r->width;
 677        unsigned h = r->height;
 678
 679        /* sanitize w and h in case someone passes ~0 as the value */
 680        w &= 0xffff;
 681        h &= 0xffff;
 682        if (!(flags & V4L2_SEL_FLAG_LE)) {
 683                w++;
 684                h++;
 685                if (w < 2)
 686                        w = 2;
 687                if (h < 2)
 688                        h = 2;
 689        }
 690        if (!(flags & V4L2_SEL_FLAG_GE)) {
 691                if (w > MAX_WIDTH)
 692                        w = MAX_WIDTH;
 693                if (h > MAX_HEIGHT)
 694                        h = MAX_HEIGHT;
 695        }
 696        w = w & ~1;
 697        h = h & ~1;
 698        if (w < 2 || h < 2)
 699                return -ERANGE;
 700        if (w > MAX_WIDTH || h > MAX_HEIGHT)
 701                return -ERANGE;
 702        if (r->top < 0)
 703                r->top = 0;
 704        if (r->left < 0)
 705                r->left = 0;
 706        /* sanitize left and top in case someone passes ~0 as the value */
 707        r->left &= 0xfffe;
 708        r->top &= 0xfffe;
 709        if (r->left + w > MAX_WIDTH)
 710                r->left = MAX_WIDTH - w;
 711        if (r->top + h > MAX_HEIGHT)
 712                r->top = MAX_HEIGHT - h;
 713        if ((flags & (V4L2_SEL_FLAG_GE | V4L2_SEL_FLAG_LE)) ==
 714                        (V4L2_SEL_FLAG_GE | V4L2_SEL_FLAG_LE) &&
 715            (r->width != w || r->height != h))
 716                return -ERANGE;
 717        r->width = w;
 718        r->height = h;
 719        return 0;
 720}
 721
 722int vivid_enum_fmt_vid(struct file *file, void  *priv,
 723                                        struct v4l2_fmtdesc *f)
 724{
 725        struct vivid_dev *dev = video_drvdata(file);
 726        const struct vivid_fmt *fmt;
 727
 728        if (f->index >= ARRAY_SIZE(vivid_formats) -
 729            (dev->multiplanar ? 0 : VIVID_MPLANAR_FORMATS))
 730                return -EINVAL;
 731
 732        fmt = &vivid_formats[f->index];
 733
 734        f->pixelformat = fmt->fourcc;
 735        return 0;
 736}
 737
 738int vidioc_enum_fmt_vid_mplane(struct file *file, void  *priv,
 739                                        struct v4l2_fmtdesc *f)
 740{
 741        struct vivid_dev *dev = video_drvdata(file);
 742
 743        if (!dev->multiplanar)
 744                return -ENOTTY;
 745        return vivid_enum_fmt_vid(file, priv, f);
 746}
 747
 748int vidioc_enum_fmt_vid(struct file *file, void  *priv,
 749                                        struct v4l2_fmtdesc *f)
 750{
 751        struct vivid_dev *dev = video_drvdata(file);
 752
 753        if (dev->multiplanar)
 754                return -ENOTTY;
 755        return vivid_enum_fmt_vid(file, priv, f);
 756}
 757
 758int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
 759{
 760        struct vivid_dev *dev = video_drvdata(file);
 761        struct video_device *vdev = video_devdata(file);
 762
 763        if (vdev->vfl_dir == VFL_DIR_RX) {
 764                if (!vivid_is_sdtv_cap(dev))
 765                        return -ENODATA;
 766                *id = dev->std_cap;
 767        } else {
 768                if (!vivid_is_svid_out(dev))
 769                        return -ENODATA;
 770                *id = dev->std_out;
 771        }
 772        return 0;
 773}
 774
 775int vidioc_g_dv_timings(struct file *file, void *_fh,
 776                                    struct v4l2_dv_timings *timings)
 777{
 778        struct vivid_dev *dev = video_drvdata(file);
 779        struct video_device *vdev = video_devdata(file);
 780
 781        if (vdev->vfl_dir == VFL_DIR_RX) {
 782                if (!vivid_is_hdmi_cap(dev))
 783                        return -ENODATA;
 784                *timings = dev->dv_timings_cap;
 785        } else {
 786                if (!vivid_is_hdmi_out(dev))
 787                        return -ENODATA;
 788                *timings = dev->dv_timings_out;
 789        }
 790        return 0;
 791}
 792
 793int vidioc_enum_dv_timings(struct file *file, void *_fh,
 794                                    struct v4l2_enum_dv_timings *timings)
 795{
 796        struct vivid_dev *dev = video_drvdata(file);
 797        struct video_device *vdev = video_devdata(file);
 798
 799        if (vdev->vfl_dir == VFL_DIR_RX) {
 800                if (!vivid_is_hdmi_cap(dev))
 801                        return -ENODATA;
 802        } else {
 803                if (!vivid_is_hdmi_out(dev))
 804                        return -ENODATA;
 805        }
 806        return v4l2_enum_dv_timings_cap(timings, &vivid_dv_timings_cap,
 807                        NULL, NULL);
 808}
 809
 810int vidioc_dv_timings_cap(struct file *file, void *_fh,
 811                                    struct v4l2_dv_timings_cap *cap)
 812{
 813        struct vivid_dev *dev = video_drvdata(file);
 814        struct video_device *vdev = video_devdata(file);
 815
 816        if (vdev->vfl_dir == VFL_DIR_RX) {
 817                if (!vivid_is_hdmi_cap(dev))
 818                        return -ENODATA;
 819        } else {
 820                if (!vivid_is_hdmi_out(dev))
 821                        return -ENODATA;
 822        }
 823        *cap = vivid_dv_timings_cap;
 824        return 0;
 825}
 826
 827int vidioc_g_edid(struct file *file, void *_fh,
 828                         struct v4l2_edid *edid)
 829{
 830        struct vivid_dev *dev = video_drvdata(file);
 831        struct video_device *vdev = video_devdata(file);
 832        struct cec_adapter *adap;
 833
 834        memset(edid->reserved, 0, sizeof(edid->reserved));
 835        if (vdev->vfl_dir == VFL_DIR_RX) {
 836                if (edid->pad >= dev->num_inputs)
 837                        return -EINVAL;
 838                if (dev->input_type[edid->pad] != HDMI)
 839                        return -EINVAL;
 840                adap = dev->cec_rx_adap;
 841        } else {
 842                unsigned int bus_idx;
 843
 844                if (edid->pad >= dev->num_outputs)
 845                        return -EINVAL;
 846                if (dev->output_type[edid->pad] != HDMI)
 847                        return -EINVAL;
 848                bus_idx = dev->cec_output2bus_map[edid->pad];
 849                adap = dev->cec_tx_adap[bus_idx];
 850        }
 851        if (edid->start_block == 0 && edid->blocks == 0) {
 852                edid->blocks = dev->edid_blocks;
 853                return 0;
 854        }
 855        if (dev->edid_blocks == 0)
 856                return -ENODATA;
 857        if (edid->start_block >= dev->edid_blocks)
 858                return -EINVAL;
 859        if (edid->start_block + edid->blocks > dev->edid_blocks)
 860                edid->blocks = dev->edid_blocks - edid->start_block;
 861        cec_set_edid_phys_addr(dev->edid, dev->edid_blocks * 128, adap->phys_addr);
 862        memcpy(edid->edid, dev->edid + edid->start_block * 128, edid->blocks * 128);
 863        return 0;
 864}
 865