linux/drivers/media/platform/rcar-vin/rcar-v4l2.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Driver for Renesas R-Car VIN
   4 *
   5 * Copyright (C) 2016 Renesas Electronics Corp.
   6 * Copyright (C) 2011-2013 Renesas Solutions Corp.
   7 * Copyright (C) 2013 Cogent Embedded, Inc., <source@cogentembedded.com>
   8 * Copyright (C) 2008 Magnus Damm
   9 *
  10 * Based on the soc-camera rcar_vin driver
  11 */
  12
  13#include <linux/pm_runtime.h>
  14
  15#include <media/v4l2-event.h>
  16#include <media/v4l2-ioctl.h>
  17#include <media/v4l2-mc.h>
  18#include <media/v4l2-rect.h>
  19
  20#include "rcar-vin.h"
  21
  22#define RVIN_DEFAULT_FORMAT     V4L2_PIX_FMT_YUYV
  23#define RVIN_DEFAULT_WIDTH      800
  24#define RVIN_DEFAULT_HEIGHT     600
  25#define RVIN_DEFAULT_FIELD      V4L2_FIELD_NONE
  26#define RVIN_DEFAULT_COLORSPACE V4L2_COLORSPACE_SRGB
  27
  28/* -----------------------------------------------------------------------------
  29 * Format Conversions
  30 */
  31
  32static const struct rvin_video_format rvin_formats[] = {
  33        {
  34                .fourcc                 = V4L2_PIX_FMT_NV12,
  35                .bpp                    = 1,
  36        },
  37        {
  38                .fourcc                 = V4L2_PIX_FMT_NV16,
  39                .bpp                    = 1,
  40        },
  41        {
  42                .fourcc                 = V4L2_PIX_FMT_YUYV,
  43                .bpp                    = 2,
  44        },
  45        {
  46                .fourcc                 = V4L2_PIX_FMT_UYVY,
  47                .bpp                    = 2,
  48        },
  49        {
  50                .fourcc                 = V4L2_PIX_FMT_RGB565,
  51                .bpp                    = 2,
  52        },
  53        {
  54                .fourcc                 = V4L2_PIX_FMT_XRGB555,
  55                .bpp                    = 2,
  56        },
  57        {
  58                .fourcc                 = V4L2_PIX_FMT_XBGR32,
  59                .bpp                    = 4,
  60        },
  61        {
  62                .fourcc                 = V4L2_PIX_FMT_ARGB555,
  63                .bpp                    = 2,
  64        },
  65        {
  66                .fourcc                 = V4L2_PIX_FMT_ABGR32,
  67                .bpp                    = 4,
  68        },
  69        {
  70                .fourcc                 = V4L2_PIX_FMT_SBGGR8,
  71                .bpp                    = 1,
  72        },
  73        {
  74                .fourcc                 = V4L2_PIX_FMT_SGBRG8,
  75                .bpp                    = 1,
  76        },
  77        {
  78                .fourcc                 = V4L2_PIX_FMT_SGRBG8,
  79                .bpp                    = 1,
  80        },
  81        {
  82                .fourcc                 = V4L2_PIX_FMT_SRGGB8,
  83                .bpp                    = 1,
  84        },
  85};
  86
  87const struct rvin_video_format *rvin_format_from_pixel(struct rvin_dev *vin,
  88                                                       u32 pixelformat)
  89{
  90        int i;
  91
  92        switch (pixelformat) {
  93        case V4L2_PIX_FMT_XBGR32:
  94                if (vin->info->model == RCAR_M1)
  95                        return NULL;
  96                break;
  97        case V4L2_PIX_FMT_NV12:
  98                /*
  99                 * If NV12 is supported it's only supported on channels 0, 1, 4,
 100                 * 5, 8, 9, 12 and 13.
 101                 */
 102                if (!vin->info->nv12 || !(BIT(vin->id) & 0x3333))
 103                        return NULL;
 104                break;
 105        default:
 106                break;
 107        }
 108
 109        for (i = 0; i < ARRAY_SIZE(rvin_formats); i++)
 110                if (rvin_formats[i].fourcc == pixelformat)
 111                        return rvin_formats + i;
 112
 113        return NULL;
 114}
 115
 116static u32 rvin_format_bytesperline(struct rvin_dev *vin,
 117                                    struct v4l2_pix_format *pix)
 118{
 119        const struct rvin_video_format *fmt;
 120        u32 align;
 121
 122        fmt = rvin_format_from_pixel(vin, pix->pixelformat);
 123
 124        if (WARN_ON(!fmt))
 125                return -EINVAL;
 126
 127        switch (pix->pixelformat) {
 128        case V4L2_PIX_FMT_NV12:
 129        case V4L2_PIX_FMT_NV16:
 130                align = 0x20;
 131                break;
 132        default:
 133                align = 0x10;
 134                break;
 135        }
 136
 137        if (V4L2_FIELD_IS_SEQUENTIAL(pix->field))
 138                align = 0x80;
 139
 140        return ALIGN(pix->width, align) * fmt->bpp;
 141}
 142
 143static u32 rvin_format_sizeimage(struct v4l2_pix_format *pix)
 144{
 145        switch (pix->pixelformat) {
 146        case V4L2_PIX_FMT_NV12:
 147                return pix->bytesperline * pix->height * 3 / 2;
 148        case V4L2_PIX_FMT_NV16:
 149                return pix->bytesperline * pix->height * 2;
 150        default:
 151                return pix->bytesperline * pix->height;
 152        }
 153}
 154
 155static void rvin_format_align(struct rvin_dev *vin, struct v4l2_pix_format *pix)
 156{
 157        u32 walign;
 158
 159        if (!rvin_format_from_pixel(vin, pix->pixelformat))
 160                pix->pixelformat = RVIN_DEFAULT_FORMAT;
 161
 162        switch (pix->field) {
 163        case V4L2_FIELD_TOP:
 164        case V4L2_FIELD_BOTTOM:
 165        case V4L2_FIELD_NONE:
 166        case V4L2_FIELD_INTERLACED_TB:
 167        case V4L2_FIELD_INTERLACED_BT:
 168        case V4L2_FIELD_INTERLACED:
 169        case V4L2_FIELD_ALTERNATE:
 170        case V4L2_FIELD_SEQ_TB:
 171        case V4L2_FIELD_SEQ_BT:
 172                break;
 173        default:
 174                pix->field = RVIN_DEFAULT_FIELD;
 175                break;
 176        }
 177
 178        /* HW limit width to a multiple of 32 (2^5) for NV12/16 else 2 (2^1) */
 179        switch (pix->pixelformat) {
 180        case V4L2_PIX_FMT_NV12:
 181        case V4L2_PIX_FMT_NV16:
 182                walign = 5;
 183                break;
 184        default:
 185                walign = 1;
 186                break;
 187        }
 188
 189        /* Limit to VIN capabilities */
 190        v4l_bound_align_image(&pix->width, 2, vin->info->max_width, walign,
 191                              &pix->height, 4, vin->info->max_height, 2, 0);
 192
 193        pix->bytesperline = rvin_format_bytesperline(vin, pix);
 194        pix->sizeimage = rvin_format_sizeimage(pix);
 195
 196        vin_dbg(vin, "Format %ux%u bpl: %u size: %u\n",
 197                pix->width, pix->height, pix->bytesperline, pix->sizeimage);
 198}
 199
 200/* -----------------------------------------------------------------------------
 201 * V4L2
 202 */
 203
 204static int rvin_reset_format(struct rvin_dev *vin)
 205{
 206        struct v4l2_subdev_format fmt = {
 207                .which = V4L2_SUBDEV_FORMAT_ACTIVE,
 208                .pad = vin->parallel->source_pad,
 209        };
 210        int ret;
 211
 212        ret = v4l2_subdev_call(vin_to_source(vin), pad, get_fmt, NULL, &fmt);
 213        if (ret)
 214                return ret;
 215
 216        v4l2_fill_pix_format(&vin->format, &fmt.format);
 217
 218        vin->src_rect.top = 0;
 219        vin->src_rect.left = 0;
 220        vin->src_rect.width = vin->format.width;
 221        vin->src_rect.height = vin->format.height;
 222
 223        /*  Make use of the hardware interlacer by default. */
 224        if (vin->format.field == V4L2_FIELD_ALTERNATE) {
 225                vin->format.field = V4L2_FIELD_INTERLACED;
 226                vin->format.height *= 2;
 227        }
 228
 229        rvin_format_align(vin, &vin->format);
 230
 231        vin->crop = vin->src_rect;
 232
 233        vin->compose.top = 0;
 234        vin->compose.left = 0;
 235        vin->compose.width = vin->format.width;
 236        vin->compose.height = vin->format.height;
 237
 238        return 0;
 239}
 240
 241static int rvin_try_format(struct rvin_dev *vin, u32 which,
 242                           struct v4l2_pix_format *pix,
 243                           struct v4l2_rect *src_rect)
 244{
 245        struct v4l2_subdev *sd = vin_to_source(vin);
 246        struct v4l2_subdev_pad_config *pad_cfg;
 247        struct v4l2_subdev_format format = {
 248                .which = which,
 249                .pad = vin->parallel->source_pad,
 250        };
 251        enum v4l2_field field;
 252        u32 width, height;
 253        int ret;
 254
 255        pad_cfg = v4l2_subdev_alloc_pad_config(sd);
 256        if (pad_cfg == NULL)
 257                return -ENOMEM;
 258
 259        if (!rvin_format_from_pixel(vin, pix->pixelformat))
 260                pix->pixelformat = RVIN_DEFAULT_FORMAT;
 261
 262        v4l2_fill_mbus_format(&format.format, pix, vin->mbus_code);
 263
 264        /* Allow the video device to override field and to scale */
 265        field = pix->field;
 266        width = pix->width;
 267        height = pix->height;
 268
 269        ret = v4l2_subdev_call(sd, pad, set_fmt, pad_cfg, &format);
 270        if (ret < 0 && ret != -ENOIOCTLCMD)
 271                goto done;
 272        ret = 0;
 273
 274        v4l2_fill_pix_format(pix, &format.format);
 275
 276        if (src_rect) {
 277                src_rect->top = 0;
 278                src_rect->left = 0;
 279                src_rect->width = pix->width;
 280                src_rect->height = pix->height;
 281        }
 282
 283        if (field != V4L2_FIELD_ANY)
 284                pix->field = field;
 285
 286        pix->width = width;
 287        pix->height = height;
 288
 289        rvin_format_align(vin, pix);
 290done:
 291        v4l2_subdev_free_pad_config(pad_cfg);
 292
 293        return ret;
 294}
 295
 296static int rvin_querycap(struct file *file, void *priv,
 297                         struct v4l2_capability *cap)
 298{
 299        struct rvin_dev *vin = video_drvdata(file);
 300
 301        strscpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
 302        strscpy(cap->card, "R_Car_VIN", sizeof(cap->card));
 303        snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
 304                 dev_name(vin->dev));
 305        return 0;
 306}
 307
 308static int rvin_try_fmt_vid_cap(struct file *file, void *priv,
 309                                struct v4l2_format *f)
 310{
 311        struct rvin_dev *vin = video_drvdata(file);
 312
 313        return rvin_try_format(vin, V4L2_SUBDEV_FORMAT_TRY, &f->fmt.pix, NULL);
 314}
 315
 316static int rvin_s_fmt_vid_cap(struct file *file, void *priv,
 317                              struct v4l2_format *f)
 318{
 319        struct rvin_dev *vin = video_drvdata(file);
 320        struct v4l2_rect fmt_rect, src_rect;
 321        int ret;
 322
 323        if (vb2_is_busy(&vin->queue))
 324                return -EBUSY;
 325
 326        ret = rvin_try_format(vin, V4L2_SUBDEV_FORMAT_ACTIVE, &f->fmt.pix,
 327                              &src_rect);
 328        if (ret)
 329                return ret;
 330
 331        vin->format = f->fmt.pix;
 332
 333        fmt_rect.top = 0;
 334        fmt_rect.left = 0;
 335        fmt_rect.width = vin->format.width;
 336        fmt_rect.height = vin->format.height;
 337
 338        v4l2_rect_map_inside(&vin->crop, &src_rect);
 339        v4l2_rect_map_inside(&vin->compose, &fmt_rect);
 340        vin->src_rect = src_rect;
 341
 342        return 0;
 343}
 344
 345static int rvin_g_fmt_vid_cap(struct file *file, void *priv,
 346                              struct v4l2_format *f)
 347{
 348        struct rvin_dev *vin = video_drvdata(file);
 349
 350        f->fmt.pix = vin->format;
 351
 352        return 0;
 353}
 354
 355static int rvin_enum_fmt_vid_cap(struct file *file, void *priv,
 356                                 struct v4l2_fmtdesc *f)
 357{
 358        struct rvin_dev *vin = video_drvdata(file);
 359        unsigned int i;
 360        int matched;
 361
 362        /*
 363         * If mbus_code is set only enumerate supported pixel formats for that
 364         * bus code. Converting from YCbCr to RGB and RGB to YCbCr is possible
 365         * with VIN, so all supported YCbCr and RGB media bus codes can produce
 366         * all of the related pixel formats. If mbus_code is not set enumerate
 367         * all possible pixelformats.
 368         *
 369         * TODO: Once raw MEDIA_BUS_FMT_SRGGB12_1X12 format is added to the
 370         * driver this needs to be extended so raw media bus code only result in
 371         * raw pixel format.
 372         */
 373        switch (f->mbus_code) {
 374        case 0:
 375        case MEDIA_BUS_FMT_YUYV8_1X16:
 376        case MEDIA_BUS_FMT_UYVY8_1X16:
 377        case MEDIA_BUS_FMT_UYVY8_2X8:
 378        case MEDIA_BUS_FMT_UYVY10_2X10:
 379        case MEDIA_BUS_FMT_RGB888_1X24:
 380                break;
 381        case MEDIA_BUS_FMT_SBGGR8_1X8:
 382                if (f->index)
 383                        return -EINVAL;
 384                f->pixelformat = V4L2_PIX_FMT_SBGGR8;
 385                return 0;
 386        case MEDIA_BUS_FMT_SGBRG8_1X8:
 387                if (f->index)
 388                        return -EINVAL;
 389                f->pixelformat = V4L2_PIX_FMT_SGBRG8;
 390                return 0;
 391        case MEDIA_BUS_FMT_SGRBG8_1X8:
 392                if (f->index)
 393                        return -EINVAL;
 394                f->pixelformat = V4L2_PIX_FMT_SGRBG8;
 395                return 0;
 396        case MEDIA_BUS_FMT_SRGGB8_1X8:
 397                if (f->index)
 398                        return -EINVAL;
 399                f->pixelformat = V4L2_PIX_FMT_SRGGB8;
 400                return 0;
 401        default:
 402                return -EINVAL;
 403        }
 404
 405        matched = -1;
 406        for (i = 0; i < ARRAY_SIZE(rvin_formats); i++) {
 407                if (rvin_format_from_pixel(vin, rvin_formats[i].fourcc))
 408                        matched++;
 409
 410                if (matched == f->index) {
 411                        f->pixelformat = rvin_formats[i].fourcc;
 412                        return 0;
 413                }
 414        }
 415
 416        return -EINVAL;
 417}
 418
 419static int rvin_g_selection(struct file *file, void *fh,
 420                            struct v4l2_selection *s)
 421{
 422        struct rvin_dev *vin = video_drvdata(file);
 423
 424        if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 425                return -EINVAL;
 426
 427        switch (s->target) {
 428        case V4L2_SEL_TGT_CROP_BOUNDS:
 429        case V4L2_SEL_TGT_CROP_DEFAULT:
 430                s->r.left = s->r.top = 0;
 431                s->r.width = vin->src_rect.width;
 432                s->r.height = vin->src_rect.height;
 433                break;
 434        case V4L2_SEL_TGT_CROP:
 435                s->r = vin->crop;
 436                break;
 437        case V4L2_SEL_TGT_COMPOSE_BOUNDS:
 438        case V4L2_SEL_TGT_COMPOSE_DEFAULT:
 439                s->r.left = s->r.top = 0;
 440                s->r.width = vin->format.width;
 441                s->r.height = vin->format.height;
 442                break;
 443        case V4L2_SEL_TGT_COMPOSE:
 444                s->r = vin->compose;
 445                break;
 446        default:
 447                return -EINVAL;
 448        }
 449
 450        return 0;
 451}
 452
 453static int rvin_s_selection(struct file *file, void *fh,
 454                            struct v4l2_selection *s)
 455{
 456        struct rvin_dev *vin = video_drvdata(file);
 457        const struct rvin_video_format *fmt;
 458        struct v4l2_rect r = s->r;
 459        struct v4l2_rect max_rect;
 460        struct v4l2_rect min_rect = {
 461                .width = 6,
 462                .height = 2,
 463        };
 464
 465        if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 466                return -EINVAL;
 467
 468        v4l2_rect_set_min_size(&r, &min_rect);
 469
 470        switch (s->target) {
 471        case V4L2_SEL_TGT_CROP:
 472                /* Can't crop outside of source input */
 473                max_rect.top = max_rect.left = 0;
 474                max_rect.width = vin->src_rect.width;
 475                max_rect.height = vin->src_rect.height;
 476                v4l2_rect_map_inside(&r, &max_rect);
 477
 478                v4l_bound_align_image(&r.width, 6, vin->src_rect.width, 0,
 479                                      &r.height, 2, vin->src_rect.height, 0, 0);
 480
 481                r.top  = clamp_t(s32, r.top, 0,
 482                                 vin->src_rect.height - r.height);
 483                r.left = clamp_t(s32, r.left, 0, vin->src_rect.width - r.width);
 484
 485                vin->crop = s->r = r;
 486
 487                vin_dbg(vin, "Cropped %dx%d@%d:%d of %dx%d\n",
 488                        r.width, r.height, r.left, r.top,
 489                        vin->src_rect.width, vin->src_rect.height);
 490                break;
 491        case V4L2_SEL_TGT_COMPOSE:
 492                /* Make sure compose rect fits inside output format */
 493                max_rect.top = max_rect.left = 0;
 494                max_rect.width = vin->format.width;
 495                max_rect.height = vin->format.height;
 496                v4l2_rect_map_inside(&r, &max_rect);
 497
 498                /*
 499                 * Composing is done by adding a offset to the buffer address,
 500                 * the HW wants this address to be aligned to HW_BUFFER_MASK.
 501                 * Make sure the top and left values meets this requirement.
 502                 */
 503                while ((r.top * vin->format.bytesperline) & HW_BUFFER_MASK)
 504                        r.top--;
 505
 506                fmt = rvin_format_from_pixel(vin, vin->format.pixelformat);
 507                while ((r.left * fmt->bpp) & HW_BUFFER_MASK)
 508                        r.left--;
 509
 510                vin->compose = s->r = r;
 511
 512                vin_dbg(vin, "Compose %dx%d@%d:%d in %dx%d\n",
 513                        r.width, r.height, r.left, r.top,
 514                        vin->format.width, vin->format.height);
 515                break;
 516        default:
 517                return -EINVAL;
 518        }
 519
 520        /* HW supports modifying configuration while running */
 521        rvin_crop_scale_comp(vin);
 522
 523        return 0;
 524}
 525
 526static int rvin_g_pixelaspect(struct file *file, void *priv,
 527                              int type, struct v4l2_fract *f)
 528{
 529        struct rvin_dev *vin = video_drvdata(file);
 530        struct v4l2_subdev *sd = vin_to_source(vin);
 531
 532        if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 533                return -EINVAL;
 534
 535        return v4l2_subdev_call(sd, video, g_pixelaspect, f);
 536}
 537
 538static int rvin_enum_input(struct file *file, void *priv,
 539                           struct v4l2_input *i)
 540{
 541        struct rvin_dev *vin = video_drvdata(file);
 542        struct v4l2_subdev *sd = vin_to_source(vin);
 543        int ret;
 544
 545        if (i->index != 0)
 546                return -EINVAL;
 547
 548        ret = v4l2_subdev_call(sd, video, g_input_status, &i->status);
 549        if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
 550                return ret;
 551
 552        i->type = V4L2_INPUT_TYPE_CAMERA;
 553
 554        if (v4l2_subdev_has_op(sd, pad, dv_timings_cap)) {
 555                i->capabilities = V4L2_IN_CAP_DV_TIMINGS;
 556                i->std = 0;
 557        } else {
 558                i->capabilities = V4L2_IN_CAP_STD;
 559                i->std = vin->vdev.tvnorms;
 560        }
 561
 562        strscpy(i->name, "Camera", sizeof(i->name));
 563
 564        return 0;
 565}
 566
 567static int rvin_g_input(struct file *file, void *priv, unsigned int *i)
 568{
 569        *i = 0;
 570        return 0;
 571}
 572
 573static int rvin_s_input(struct file *file, void *priv, unsigned int i)
 574{
 575        if (i > 0)
 576                return -EINVAL;
 577        return 0;
 578}
 579
 580static int rvin_querystd(struct file *file, void *priv, v4l2_std_id *a)
 581{
 582        struct rvin_dev *vin = video_drvdata(file);
 583        struct v4l2_subdev *sd = vin_to_source(vin);
 584
 585        return v4l2_subdev_call(sd, video, querystd, a);
 586}
 587
 588static int rvin_s_std(struct file *file, void *priv, v4l2_std_id a)
 589{
 590        struct rvin_dev *vin = video_drvdata(file);
 591        int ret;
 592
 593        ret = v4l2_subdev_call(vin_to_source(vin), video, s_std, a);
 594        if (ret < 0)
 595                return ret;
 596
 597        vin->std = a;
 598
 599        /* Changing the standard will change the width/height */
 600        return rvin_reset_format(vin);
 601}
 602
 603static int rvin_g_std(struct file *file, void *priv, v4l2_std_id *a)
 604{
 605        struct rvin_dev *vin = video_drvdata(file);
 606
 607        if (v4l2_subdev_has_op(vin_to_source(vin), pad, dv_timings_cap))
 608                return -ENOIOCTLCMD;
 609
 610        *a = vin->std;
 611
 612        return 0;
 613}
 614
 615static int rvin_subscribe_event(struct v4l2_fh *fh,
 616                                const struct v4l2_event_subscription *sub)
 617{
 618        switch (sub->type) {
 619        case V4L2_EVENT_SOURCE_CHANGE:
 620                return v4l2_event_subscribe(fh, sub, 4, NULL);
 621        }
 622        return v4l2_ctrl_subscribe_event(fh, sub);
 623}
 624
 625static int rvin_enum_dv_timings(struct file *file, void *priv_fh,
 626                                struct v4l2_enum_dv_timings *timings)
 627{
 628        struct rvin_dev *vin = video_drvdata(file);
 629        struct v4l2_subdev *sd = vin_to_source(vin);
 630        int ret;
 631
 632        if (timings->pad)
 633                return -EINVAL;
 634
 635        timings->pad = vin->parallel->sink_pad;
 636
 637        ret = v4l2_subdev_call(sd, pad, enum_dv_timings, timings);
 638
 639        timings->pad = 0;
 640
 641        return ret;
 642}
 643
 644static int rvin_s_dv_timings(struct file *file, void *priv_fh,
 645                             struct v4l2_dv_timings *timings)
 646{
 647        struct rvin_dev *vin = video_drvdata(file);
 648        struct v4l2_subdev *sd = vin_to_source(vin);
 649        int ret;
 650
 651        ret = v4l2_subdev_call(sd, video, s_dv_timings, timings);
 652        if (ret)
 653                return ret;
 654
 655        /* Changing the timings will change the width/height */
 656        return rvin_reset_format(vin);
 657}
 658
 659static int rvin_g_dv_timings(struct file *file, void *priv_fh,
 660                             struct v4l2_dv_timings *timings)
 661{
 662        struct rvin_dev *vin = video_drvdata(file);
 663        struct v4l2_subdev *sd = vin_to_source(vin);
 664
 665        return v4l2_subdev_call(sd, video, g_dv_timings, timings);
 666}
 667
 668static int rvin_query_dv_timings(struct file *file, void *priv_fh,
 669                                 struct v4l2_dv_timings *timings)
 670{
 671        struct rvin_dev *vin = video_drvdata(file);
 672        struct v4l2_subdev *sd = vin_to_source(vin);
 673
 674        return v4l2_subdev_call(sd, video, query_dv_timings, timings);
 675}
 676
 677static int rvin_dv_timings_cap(struct file *file, void *priv_fh,
 678                               struct v4l2_dv_timings_cap *cap)
 679{
 680        struct rvin_dev *vin = video_drvdata(file);
 681        struct v4l2_subdev *sd = vin_to_source(vin);
 682        int ret;
 683
 684        if (cap->pad)
 685                return -EINVAL;
 686
 687        cap->pad = vin->parallel->sink_pad;
 688
 689        ret = v4l2_subdev_call(sd, pad, dv_timings_cap, cap);
 690
 691        cap->pad = 0;
 692
 693        return ret;
 694}
 695
 696static int rvin_g_edid(struct file *file, void *fh, struct v4l2_edid *edid)
 697{
 698        struct rvin_dev *vin = video_drvdata(file);
 699        struct v4l2_subdev *sd = vin_to_source(vin);
 700        int ret;
 701
 702        if (edid->pad)
 703                return -EINVAL;
 704
 705        edid->pad = vin->parallel->sink_pad;
 706
 707        ret = v4l2_subdev_call(sd, pad, get_edid, edid);
 708
 709        edid->pad = 0;
 710
 711        return ret;
 712}
 713
 714static int rvin_s_edid(struct file *file, void *fh, struct v4l2_edid *edid)
 715{
 716        struct rvin_dev *vin = video_drvdata(file);
 717        struct v4l2_subdev *sd = vin_to_source(vin);
 718        int ret;
 719
 720        if (edid->pad)
 721                return -EINVAL;
 722
 723        edid->pad = vin->parallel->sink_pad;
 724
 725        ret = v4l2_subdev_call(sd, pad, set_edid, edid);
 726
 727        edid->pad = 0;
 728
 729        return ret;
 730}
 731
 732static const struct v4l2_ioctl_ops rvin_ioctl_ops = {
 733        .vidioc_querycap                = rvin_querycap,
 734        .vidioc_try_fmt_vid_cap         = rvin_try_fmt_vid_cap,
 735        .vidioc_g_fmt_vid_cap           = rvin_g_fmt_vid_cap,
 736        .vidioc_s_fmt_vid_cap           = rvin_s_fmt_vid_cap,
 737        .vidioc_enum_fmt_vid_cap        = rvin_enum_fmt_vid_cap,
 738
 739        .vidioc_g_selection             = rvin_g_selection,
 740        .vidioc_s_selection             = rvin_s_selection,
 741
 742        .vidioc_g_pixelaspect           = rvin_g_pixelaspect,
 743
 744        .vidioc_enum_input              = rvin_enum_input,
 745        .vidioc_g_input                 = rvin_g_input,
 746        .vidioc_s_input                 = rvin_s_input,
 747
 748        .vidioc_dv_timings_cap          = rvin_dv_timings_cap,
 749        .vidioc_enum_dv_timings         = rvin_enum_dv_timings,
 750        .vidioc_g_dv_timings            = rvin_g_dv_timings,
 751        .vidioc_s_dv_timings            = rvin_s_dv_timings,
 752        .vidioc_query_dv_timings        = rvin_query_dv_timings,
 753
 754        .vidioc_g_edid                  = rvin_g_edid,
 755        .vidioc_s_edid                  = rvin_s_edid,
 756
 757        .vidioc_querystd                = rvin_querystd,
 758        .vidioc_g_std                   = rvin_g_std,
 759        .vidioc_s_std                   = rvin_s_std,
 760
 761        .vidioc_reqbufs                 = vb2_ioctl_reqbufs,
 762        .vidioc_create_bufs             = vb2_ioctl_create_bufs,
 763        .vidioc_querybuf                = vb2_ioctl_querybuf,
 764        .vidioc_qbuf                    = vb2_ioctl_qbuf,
 765        .vidioc_dqbuf                   = vb2_ioctl_dqbuf,
 766        .vidioc_expbuf                  = vb2_ioctl_expbuf,
 767        .vidioc_prepare_buf             = vb2_ioctl_prepare_buf,
 768        .vidioc_streamon                = vb2_ioctl_streamon,
 769        .vidioc_streamoff               = vb2_ioctl_streamoff,
 770
 771        .vidioc_log_status              = v4l2_ctrl_log_status,
 772        .vidioc_subscribe_event         = rvin_subscribe_event,
 773        .vidioc_unsubscribe_event       = v4l2_event_unsubscribe,
 774};
 775
 776/* -----------------------------------------------------------------------------
 777 * V4L2 Media Controller
 778 */
 779
 780static void rvin_mc_try_format(struct rvin_dev *vin,
 781                               struct v4l2_pix_format *pix)
 782{
 783        /*
 784         * The V4L2 specification clearly documents the colorspace fields
 785         * as being set by drivers for capture devices. Using the values
 786         * supplied by userspace thus wouldn't comply with the API. Until
 787         * the API is updated force fixed values.
 788         */
 789        pix->colorspace = RVIN_DEFAULT_COLORSPACE;
 790        pix->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(pix->colorspace);
 791        pix->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(pix->colorspace);
 792        pix->quantization = V4L2_MAP_QUANTIZATION_DEFAULT(true, pix->colorspace,
 793                                                          pix->ycbcr_enc);
 794
 795        rvin_format_align(vin, pix);
 796}
 797
 798static int rvin_mc_try_fmt_vid_cap(struct file *file, void *priv,
 799                                   struct v4l2_format *f)
 800{
 801        struct rvin_dev *vin = video_drvdata(file);
 802
 803        rvin_mc_try_format(vin, &f->fmt.pix);
 804
 805        return 0;
 806}
 807
 808static int rvin_mc_s_fmt_vid_cap(struct file *file, void *priv,
 809                                 struct v4l2_format *f)
 810{
 811        struct rvin_dev *vin = video_drvdata(file);
 812
 813        if (vb2_is_busy(&vin->queue))
 814                return -EBUSY;
 815
 816        rvin_mc_try_format(vin, &f->fmt.pix);
 817
 818        vin->format = f->fmt.pix;
 819
 820        vin->crop.top = 0;
 821        vin->crop.left = 0;
 822        vin->crop.width = vin->format.width;
 823        vin->crop.height = vin->format.height;
 824        vin->compose = vin->crop;
 825
 826        return 0;
 827}
 828
 829static const struct v4l2_ioctl_ops rvin_mc_ioctl_ops = {
 830        .vidioc_querycap                = rvin_querycap,
 831        .vidioc_try_fmt_vid_cap         = rvin_mc_try_fmt_vid_cap,
 832        .vidioc_g_fmt_vid_cap           = rvin_g_fmt_vid_cap,
 833        .vidioc_s_fmt_vid_cap           = rvin_mc_s_fmt_vid_cap,
 834        .vidioc_enum_fmt_vid_cap        = rvin_enum_fmt_vid_cap,
 835
 836        .vidioc_reqbufs                 = vb2_ioctl_reqbufs,
 837        .vidioc_create_bufs             = vb2_ioctl_create_bufs,
 838        .vidioc_querybuf                = vb2_ioctl_querybuf,
 839        .vidioc_qbuf                    = vb2_ioctl_qbuf,
 840        .vidioc_dqbuf                   = vb2_ioctl_dqbuf,
 841        .vidioc_expbuf                  = vb2_ioctl_expbuf,
 842        .vidioc_prepare_buf             = vb2_ioctl_prepare_buf,
 843        .vidioc_streamon                = vb2_ioctl_streamon,
 844        .vidioc_streamoff               = vb2_ioctl_streamoff,
 845
 846        .vidioc_log_status              = v4l2_ctrl_log_status,
 847        .vidioc_subscribe_event         = rvin_subscribe_event,
 848        .vidioc_unsubscribe_event       = v4l2_event_unsubscribe,
 849};
 850
 851/* -----------------------------------------------------------------------------
 852 * File Operations
 853 */
 854
 855static int rvin_power_parallel(struct rvin_dev *vin, bool on)
 856{
 857        struct v4l2_subdev *sd = vin_to_source(vin);
 858        int power = on ? 1 : 0;
 859        int ret;
 860
 861        ret = v4l2_subdev_call(sd, core, s_power, power);
 862        if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
 863                return ret;
 864
 865        return 0;
 866}
 867
 868static int rvin_open(struct file *file)
 869{
 870        struct rvin_dev *vin = video_drvdata(file);
 871        int ret;
 872
 873        ret = pm_runtime_get_sync(vin->dev);
 874        if (ret < 0) {
 875                pm_runtime_put_noidle(vin->dev);
 876                return ret;
 877        }
 878
 879        ret = mutex_lock_interruptible(&vin->lock);
 880        if (ret)
 881                goto err_pm;
 882
 883        file->private_data = vin;
 884
 885        ret = v4l2_fh_open(file);
 886        if (ret)
 887                goto err_unlock;
 888
 889        if (vin->info->use_mc)
 890                ret = v4l2_pipeline_pm_get(&vin->vdev.entity);
 891        else if (v4l2_fh_is_singular_file(file))
 892                ret = rvin_power_parallel(vin, true);
 893
 894        if (ret < 0)
 895                goto err_open;
 896
 897        ret = v4l2_ctrl_handler_setup(&vin->ctrl_handler);
 898        if (ret)
 899                goto err_power;
 900
 901        mutex_unlock(&vin->lock);
 902
 903        return 0;
 904err_power:
 905        if (vin->info->use_mc)
 906                v4l2_pipeline_pm_put(&vin->vdev.entity);
 907        else if (v4l2_fh_is_singular_file(file))
 908                rvin_power_parallel(vin, false);
 909err_open:
 910        v4l2_fh_release(file);
 911err_unlock:
 912        mutex_unlock(&vin->lock);
 913err_pm:
 914        pm_runtime_put(vin->dev);
 915
 916        return ret;
 917}
 918
 919static int rvin_release(struct file *file)
 920{
 921        struct rvin_dev *vin = video_drvdata(file);
 922        bool fh_singular;
 923        int ret;
 924
 925        mutex_lock(&vin->lock);
 926
 927        /* Save the singular status before we call the clean-up helper */
 928        fh_singular = v4l2_fh_is_singular_file(file);
 929
 930        /* the release helper will cleanup any on-going streaming */
 931        ret = _vb2_fop_release(file, NULL);
 932
 933        if (vin->info->use_mc) {
 934                v4l2_pipeline_pm_put(&vin->vdev.entity);
 935        } else {
 936                if (fh_singular)
 937                        rvin_power_parallel(vin, false);
 938        }
 939
 940        mutex_unlock(&vin->lock);
 941
 942        pm_runtime_put(vin->dev);
 943
 944        return ret;
 945}
 946
 947static const struct v4l2_file_operations rvin_fops = {
 948        .owner          = THIS_MODULE,
 949        .unlocked_ioctl = video_ioctl2,
 950        .open           = rvin_open,
 951        .release        = rvin_release,
 952        .poll           = vb2_fop_poll,
 953        .mmap           = vb2_fop_mmap,
 954        .read           = vb2_fop_read,
 955};
 956
 957void rvin_v4l2_unregister(struct rvin_dev *vin)
 958{
 959        if (!video_is_registered(&vin->vdev))
 960                return;
 961
 962        v4l2_info(&vin->v4l2_dev, "Removing %s\n",
 963                  video_device_node_name(&vin->vdev));
 964
 965        /* Checks internally if vdev have been init or not */
 966        video_unregister_device(&vin->vdev);
 967}
 968
 969static void rvin_notify(struct v4l2_subdev *sd,
 970                        unsigned int notification, void *arg)
 971{
 972        struct rvin_dev *vin =
 973                container_of(sd->v4l2_dev, struct rvin_dev, v4l2_dev);
 974
 975        switch (notification) {
 976        case V4L2_DEVICE_NOTIFY_EVENT:
 977                v4l2_event_queue(&vin->vdev, arg);
 978                break;
 979        default:
 980                break;
 981        }
 982}
 983
 984int rvin_v4l2_register(struct rvin_dev *vin)
 985{
 986        struct video_device *vdev = &vin->vdev;
 987        int ret;
 988
 989        vin->v4l2_dev.notify = rvin_notify;
 990
 991        /* video node */
 992        vdev->v4l2_dev = &vin->v4l2_dev;
 993        vdev->queue = &vin->queue;
 994        snprintf(vdev->name, sizeof(vdev->name), "VIN%u output", vin->id);
 995        vdev->release = video_device_release_empty;
 996        vdev->lock = &vin->lock;
 997        vdev->fops = &rvin_fops;
 998        vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
 999                V4L2_CAP_READWRITE;
1000
1001        /* Set a default format */
1002        vin->format.pixelformat = RVIN_DEFAULT_FORMAT;
1003        vin->format.width = RVIN_DEFAULT_WIDTH;
1004        vin->format.height = RVIN_DEFAULT_HEIGHT;
1005        vin->format.field = RVIN_DEFAULT_FIELD;
1006        vin->format.colorspace = RVIN_DEFAULT_COLORSPACE;
1007
1008        if (vin->info->use_mc) {
1009                vdev->device_caps |= V4L2_CAP_IO_MC;
1010                vdev->ioctl_ops = &rvin_mc_ioctl_ops;
1011        } else {
1012                vdev->ioctl_ops = &rvin_ioctl_ops;
1013                rvin_reset_format(vin);
1014        }
1015
1016        rvin_format_align(vin, &vin->format);
1017
1018        ret = video_register_device(&vin->vdev, VFL_TYPE_VIDEO, -1);
1019        if (ret) {
1020                vin_err(vin, "Failed to register video device\n");
1021                return ret;
1022        }
1023
1024        video_set_drvdata(&vin->vdev, vin);
1025
1026        v4l2_info(&vin->v4l2_dev, "Device registered as %s\n",
1027                  video_device_node_name(&vin->vdev));
1028
1029        return ret;
1030}
1031