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