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