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                .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_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        /* Multiplanar formats */
 450
 451        {
 452                .fourcc   = V4L2_PIX_FMT_NV16M,
 453                .vdownsampling = { 1, 1 },
 454                .bit_depth = { 8, 8 },
 455                .is_yuv   = true,
 456                .planes   = 2,
 457                .buffers = 2,
 458                .data_offset = { PLANE0_DATA_OFFSET, 0 },
 459        },
 460        {
 461                .fourcc   = V4L2_PIX_FMT_NV61M,
 462                .vdownsampling = { 1, 1 },
 463                .bit_depth = { 8, 8 },
 464                .is_yuv   = true,
 465                .planes   = 2,
 466                .buffers = 2,
 467                .data_offset = { 0, PLANE0_DATA_OFFSET },
 468        },
 469        {
 470                .fourcc   = V4L2_PIX_FMT_YUV420M,
 471                .vdownsampling = { 1, 2, 2 },
 472                .bit_depth = { 8, 4, 4 },
 473                .is_yuv   = true,
 474                .planes   = 3,
 475                .buffers = 3,
 476        },
 477        {
 478                .fourcc   = V4L2_PIX_FMT_YVU420M,
 479                .vdownsampling = { 1, 2, 2 },
 480                .bit_depth = { 8, 4, 4 },
 481                .is_yuv   = true,
 482                .planes   = 3,
 483                .buffers = 3,
 484        },
 485        {
 486                .fourcc   = V4L2_PIX_FMT_NV12M,
 487                .vdownsampling = { 1, 2 },
 488                .bit_depth = { 8, 8 },
 489                .is_yuv   = true,
 490                .planes   = 2,
 491                .buffers = 2,
 492        },
 493        {
 494                .fourcc   = V4L2_PIX_FMT_NV21M,
 495                .vdownsampling = { 1, 2 },
 496                .bit_depth = { 8, 8 },
 497                .is_yuv   = true,
 498                .planes   = 2,
 499                .buffers = 2,
 500        },
 501        {
 502                .fourcc   = V4L2_PIX_FMT_YUV422M,
 503                .vdownsampling = { 1, 1, 1 },
 504                .bit_depth = { 8, 4, 4 },
 505                .is_yuv   = true,
 506                .planes   = 3,
 507                .buffers = 3,
 508        },
 509        {
 510                .fourcc   = V4L2_PIX_FMT_YVU422M,
 511                .vdownsampling = { 1, 1, 1 },
 512                .bit_depth = { 8, 4, 4 },
 513                .is_yuv   = true,
 514                .planes   = 3,
 515                .buffers = 3,
 516        },
 517        {
 518                .fourcc   = V4L2_PIX_FMT_YUV444M,
 519                .vdownsampling = { 1, 1, 1 },
 520                .bit_depth = { 8, 8, 8 },
 521                .is_yuv   = true,
 522                .planes   = 3,
 523                .buffers = 3,
 524        },
 525        {
 526                .fourcc   = V4L2_PIX_FMT_YVU444M,
 527                .vdownsampling = { 1, 1, 1 },
 528                .bit_depth = { 8, 8, 8 },
 529                .is_yuv   = true,
 530                .planes   = 3,
 531                .buffers = 3,
 532        },
 533};
 534
 535/* There are this many multiplanar formats in the list */
 536#define VIVID_MPLANAR_FORMATS 10
 537
 538const struct vivid_fmt *vivid_get_format(struct vivid_dev *dev, u32 pixelformat)
 539{
 540        const struct vivid_fmt *fmt;
 541        unsigned k;
 542
 543        for (k = 0; k < ARRAY_SIZE(vivid_formats); k++) {
 544                fmt = &vivid_formats[k];
 545                if (fmt->fourcc == pixelformat)
 546                        if (fmt->buffers == 1 || dev->multiplanar)
 547                                return fmt;
 548        }
 549
 550        return NULL;
 551}
 552
 553bool vivid_vid_can_loop(struct vivid_dev *dev)
 554{
 555        if (dev->src_rect.width != dev->sink_rect.width ||
 556            dev->src_rect.height != dev->sink_rect.height)
 557                return false;
 558        if (dev->fmt_cap->fourcc != dev->fmt_out->fourcc)
 559                return false;
 560        if (dev->field_cap != dev->field_out)
 561                return false;
 562        /*
 563         * While this can be supported, it is just too much work
 564         * to actually implement.
 565         */
 566        if (dev->field_cap == V4L2_FIELD_SEQ_TB ||
 567            dev->field_cap == V4L2_FIELD_SEQ_BT)
 568                return false;
 569        if (vivid_is_svid_cap(dev) && vivid_is_svid_out(dev)) {
 570                if (!(dev->std_cap & V4L2_STD_525_60) !=
 571                    !(dev->std_out & V4L2_STD_525_60))
 572                        return false;
 573                return true;
 574        }
 575        if (vivid_is_hdmi_cap(dev) && vivid_is_hdmi_out(dev))
 576                return true;
 577        return false;
 578}
 579
 580void vivid_send_source_change(struct vivid_dev *dev, unsigned type)
 581{
 582        struct v4l2_event ev = {
 583                .type = V4L2_EVENT_SOURCE_CHANGE,
 584                .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
 585        };
 586        unsigned i;
 587
 588        for (i = 0; i < dev->num_inputs; i++) {
 589                ev.id = i;
 590                if (dev->input_type[i] == type) {
 591                        if (video_is_registered(&dev->vid_cap_dev) && dev->has_vid_cap)
 592                                v4l2_event_queue(&dev->vid_cap_dev, &ev);
 593                        if (video_is_registered(&dev->vbi_cap_dev) && dev->has_vbi_cap)
 594                                v4l2_event_queue(&dev->vbi_cap_dev, &ev);
 595                }
 596        }
 597}
 598
 599/*
 600 * Conversion function that converts a single-planar format to a
 601 * single-plane multiplanar format.
 602 */
 603void fmt_sp2mp(const struct v4l2_format *sp_fmt, struct v4l2_format *mp_fmt)
 604{
 605        struct v4l2_pix_format_mplane *mp = &mp_fmt->fmt.pix_mp;
 606        struct v4l2_plane_pix_format *ppix = &mp->plane_fmt[0];
 607        const struct v4l2_pix_format *pix = &sp_fmt->fmt.pix;
 608        bool is_out = sp_fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT;
 609
 610        memset(mp->reserved, 0, sizeof(mp->reserved));
 611        mp_fmt->type = is_out ? V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE :
 612                           V4L2_CAP_VIDEO_CAPTURE_MPLANE;
 613        mp->width = pix->width;
 614        mp->height = pix->height;
 615        mp->pixelformat = pix->pixelformat;
 616        mp->field = pix->field;
 617        mp->colorspace = pix->colorspace;
 618        mp->xfer_func = pix->xfer_func;
 619        mp->ycbcr_enc = pix->ycbcr_enc;
 620        mp->quantization = pix->quantization;
 621        mp->num_planes = 1;
 622        mp->flags = pix->flags;
 623        ppix->sizeimage = pix->sizeimage;
 624        ppix->bytesperline = pix->bytesperline;
 625        memset(ppix->reserved, 0, sizeof(ppix->reserved));
 626}
 627
 628int fmt_sp2mp_func(struct file *file, void *priv,
 629                struct v4l2_format *f, fmtfunc func)
 630{
 631        struct v4l2_format fmt;
 632        struct v4l2_pix_format_mplane *mp = &fmt.fmt.pix_mp;
 633        struct v4l2_plane_pix_format *ppix = &mp->plane_fmt[0];
 634        struct v4l2_pix_format *pix = &f->fmt.pix;
 635        int ret;
 636
 637        /* Converts to a mplane format */
 638        fmt_sp2mp(f, &fmt);
 639        /* Passes it to the generic mplane format function */
 640        ret = func(file, priv, &fmt);
 641        /* Copies back the mplane data to the single plane format */
 642        pix->width = mp->width;
 643        pix->height = mp->height;
 644        pix->pixelformat = mp->pixelformat;
 645        pix->field = mp->field;
 646        pix->colorspace = mp->colorspace;
 647        pix->xfer_func = mp->xfer_func;
 648        pix->ycbcr_enc = mp->ycbcr_enc;
 649        pix->quantization = mp->quantization;
 650        pix->sizeimage = ppix->sizeimage;
 651        pix->bytesperline = ppix->bytesperline;
 652        pix->flags = mp->flags;
 653        return ret;
 654}
 655
 656int vivid_vid_adjust_sel(unsigned flags, struct v4l2_rect *r)
 657{
 658        unsigned w = r->width;
 659        unsigned h = r->height;
 660
 661        /* sanitize w and h in case someone passes ~0 as the value */
 662        w &= 0xffff;
 663        h &= 0xffff;
 664        if (!(flags & V4L2_SEL_FLAG_LE)) {
 665                w++;
 666                h++;
 667                if (w < 2)
 668                        w = 2;
 669                if (h < 2)
 670                        h = 2;
 671        }
 672        if (!(flags & V4L2_SEL_FLAG_GE)) {
 673                if (w > MAX_WIDTH)
 674                        w = MAX_WIDTH;
 675                if (h > MAX_HEIGHT)
 676                        h = MAX_HEIGHT;
 677        }
 678        w = w & ~1;
 679        h = h & ~1;
 680        if (w < 2 || h < 2)
 681                return -ERANGE;
 682        if (w > MAX_WIDTH || h > MAX_HEIGHT)
 683                return -ERANGE;
 684        if (r->top < 0)
 685                r->top = 0;
 686        if (r->left < 0)
 687                r->left = 0;
 688        /* sanitize left and top in case someone passes ~0 as the value */
 689        r->left &= 0xfffe;
 690        r->top &= 0xfffe;
 691        if (r->left + w > MAX_WIDTH)
 692                r->left = MAX_WIDTH - w;
 693        if (r->top + h > MAX_HEIGHT)
 694                r->top = MAX_HEIGHT - h;
 695        if ((flags & (V4L2_SEL_FLAG_GE | V4L2_SEL_FLAG_LE)) ==
 696                        (V4L2_SEL_FLAG_GE | V4L2_SEL_FLAG_LE) &&
 697            (r->width != w || r->height != h))
 698                return -ERANGE;
 699        r->width = w;
 700        r->height = h;
 701        return 0;
 702}
 703
 704int vivid_enum_fmt_vid(struct file *file, void  *priv,
 705                                        struct v4l2_fmtdesc *f)
 706{
 707        struct vivid_dev *dev = video_drvdata(file);
 708        const struct vivid_fmt *fmt;
 709
 710        if (f->index >= ARRAY_SIZE(vivid_formats) -
 711            (dev->multiplanar ? 0 : VIVID_MPLANAR_FORMATS))
 712                return -EINVAL;
 713
 714        fmt = &vivid_formats[f->index];
 715
 716        f->pixelformat = fmt->fourcc;
 717        return 0;
 718}
 719
 720int vidioc_enum_fmt_vid_mplane(struct file *file, void  *priv,
 721                                        struct v4l2_fmtdesc *f)
 722{
 723        struct vivid_dev *dev = video_drvdata(file);
 724
 725        if (!dev->multiplanar)
 726                return -ENOTTY;
 727        return vivid_enum_fmt_vid(file, priv, f);
 728}
 729
 730int vidioc_enum_fmt_vid(struct file *file, void  *priv,
 731                                        struct v4l2_fmtdesc *f)
 732{
 733        struct vivid_dev *dev = video_drvdata(file);
 734
 735        if (dev->multiplanar)
 736                return -ENOTTY;
 737        return vivid_enum_fmt_vid(file, priv, f);
 738}
 739
 740int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
 741{
 742        struct vivid_dev *dev = video_drvdata(file);
 743        struct video_device *vdev = video_devdata(file);
 744
 745        if (vdev->vfl_dir == VFL_DIR_RX) {
 746                if (!vivid_is_sdtv_cap(dev))
 747                        return -ENODATA;
 748                *id = dev->std_cap;
 749        } else {
 750                if (!vivid_is_svid_out(dev))
 751                        return -ENODATA;
 752                *id = dev->std_out;
 753        }
 754        return 0;
 755}
 756
 757int vidioc_g_dv_timings(struct file *file, void *_fh,
 758                                    struct v4l2_dv_timings *timings)
 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_hdmi_cap(dev))
 765                        return -ENODATA;
 766                *timings = dev->dv_timings_cap;
 767        } else {
 768                if (!vivid_is_hdmi_out(dev))
 769                        return -ENODATA;
 770                *timings = dev->dv_timings_out;
 771        }
 772        return 0;
 773}
 774
 775int vidioc_enum_dv_timings(struct file *file, void *_fh,
 776                                    struct v4l2_enum_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        } else {
 785                if (!vivid_is_hdmi_out(dev))
 786                        return -ENODATA;
 787        }
 788        return v4l2_enum_dv_timings_cap(timings, &vivid_dv_timings_cap,
 789                        NULL, NULL);
 790}
 791
 792int vidioc_dv_timings_cap(struct file *file, void *_fh,
 793                                    struct v4l2_dv_timings_cap *cap)
 794{
 795        struct vivid_dev *dev = video_drvdata(file);
 796        struct video_device *vdev = video_devdata(file);
 797
 798        if (vdev->vfl_dir == VFL_DIR_RX) {
 799                if (!vivid_is_hdmi_cap(dev))
 800                        return -ENODATA;
 801        } else {
 802                if (!vivid_is_hdmi_out(dev))
 803                        return -ENODATA;
 804        }
 805        *cap = vivid_dv_timings_cap;
 806        return 0;
 807}
 808
 809int vidioc_g_edid(struct file *file, void *_fh,
 810                         struct v4l2_edid *edid)
 811{
 812        struct vivid_dev *dev = video_drvdata(file);
 813        struct video_device *vdev = video_devdata(file);
 814        struct cec_adapter *adap;
 815
 816        memset(edid->reserved, 0, sizeof(edid->reserved));
 817        if (vdev->vfl_dir == VFL_DIR_RX) {
 818                if (edid->pad >= dev->num_inputs)
 819                        return -EINVAL;
 820                if (dev->input_type[edid->pad] != HDMI)
 821                        return -EINVAL;
 822                adap = dev->cec_rx_adap;
 823        } else {
 824                unsigned int bus_idx;
 825
 826                if (edid->pad >= dev->num_outputs)
 827                        return -EINVAL;
 828                if (dev->output_type[edid->pad] != HDMI)
 829                        return -EINVAL;
 830                bus_idx = dev->cec_output2bus_map[edid->pad];
 831                adap = dev->cec_tx_adap[bus_idx];
 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        cec_set_edid_phys_addr(edid->edid, edid->blocks * 128, adap->phys_addr);
 845        return 0;
 846}
 847