1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Samsung S5P/EXYNOS4 SoC series FIMC (video postprocessor) driver 4 * 5 * Copyright (C) 2012 - 2013 Samsung Electronics Co., Ltd. 6 * Sylwester Nawrocki <s.nawrocki@samsung.com> 7 */ 8 9 #include <linux/module.h> 10 #include <linux/kernel.h> 11 #include <linux/types.h> 12 #include <linux/errno.h> 13 #include <linux/bug.h> 14 #include <linux/interrupt.h> 15 #include <linux/device.h> 16 #include <linux/platform_device.h> 17 #include <linux/pm_runtime.h> 18 #include <linux/list.h> 19 #include <linux/io.h> 20 #include <linux/slab.h> 21 #include <linux/clk.h> 22 #include <media/v4l2-ioctl.h> 23 #include <media/videobuf2-v4l2.h> 24 #include <media/videobuf2-dma-contig.h> 25 26 #include "common.h" 27 #include "fimc-core.h" 28 #include "fimc-reg.h" 29 #include "media-dev.h" 30 31 static unsigned int get_m2m_fmt_flags(unsigned int stream_type) 32 { 33 if (stream_type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) 34 return FMT_FLAGS_M2M_IN; 35 else 36 return FMT_FLAGS_M2M_OUT; 37 } 38 39 void fimc_m2m_job_finish(struct fimc_ctx *ctx, int vb_state) 40 { 41 struct vb2_v4l2_buffer *src_vb, *dst_vb; 42 43 if (!ctx || !ctx->fh.m2m_ctx) 44 return; 45 46 src_vb = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); 47 dst_vb = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); 48 49 if (src_vb) 50 v4l2_m2m_buf_done(src_vb, vb_state); 51 if (dst_vb) 52 v4l2_m2m_buf_done(dst_vb, vb_state); 53 if (src_vb && dst_vb) 54 v4l2_m2m_job_finish(ctx->fimc_dev->m2m.m2m_dev, 55 ctx->fh.m2m_ctx); 56 } 57 58 /* Complete the transaction which has been scheduled for execution. */ 59 static void fimc_m2m_shutdown(struct fimc_ctx *ctx) 60 { 61 struct fimc_dev *fimc = ctx->fimc_dev; 62 63 if (!fimc_m2m_pending(fimc)) 64 return; 65 66 fimc_ctx_state_set(FIMC_CTX_SHUT, ctx); 67 68 wait_event_timeout(fimc->irq_queue, 69 !fimc_ctx_state_is_set(FIMC_CTX_SHUT, ctx), 70 FIMC_SHUTDOWN_TIMEOUT); 71 } 72 73 static int start_streaming(struct vb2_queue *q, unsigned int count) 74 { 75 struct fimc_ctx *ctx = q->drv_priv; 76 77 return pm_runtime_resume_and_get(&ctx->fimc_dev->pdev->dev); 78 } 79 80 static void stop_streaming(struct vb2_queue *q) 81 { 82 struct fimc_ctx *ctx = q->drv_priv; 83 84 fimc_m2m_shutdown(ctx); 85 fimc_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR); 86 pm_runtime_put(&ctx->fimc_dev->pdev->dev); 87 } 88 89 static void fimc_device_run(void *priv) 90 { 91 struct vb2_v4l2_buffer *src_vb, *dst_vb; 92 struct fimc_ctx *ctx = priv; 93 struct fimc_frame *sf, *df; 94 struct fimc_dev *fimc; 95 unsigned long flags; 96 int ret; 97 98 if (WARN(!ctx, "Null context\n")) 99 return; 100 101 fimc = ctx->fimc_dev; 102 spin_lock_irqsave(&fimc->slock, flags); 103 104 set_bit(ST_M2M_PEND, &fimc->state); 105 sf = &ctx->s_frame; 106 df = &ctx->d_frame; 107 108 if (ctx->state & FIMC_PARAMS) { 109 /* Prepare the DMA offsets for scaler */ 110 fimc_prepare_dma_offset(ctx, sf); 111 fimc_prepare_dma_offset(ctx, df); 112 } 113 114 src_vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); 115 ret = fimc_prepare_addr(ctx, &src_vb->vb2_buf, sf, &sf->addr); 116 if (ret) 117 goto dma_unlock; 118 119 dst_vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); 120 ret = fimc_prepare_addr(ctx, &dst_vb->vb2_buf, df, &df->addr); 121 if (ret) 122 goto dma_unlock; 123 124 dst_vb->vb2_buf.timestamp = src_vb->vb2_buf.timestamp; 125 dst_vb->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; 126 dst_vb->flags |= 127 src_vb->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK; 128 129 /* Reconfigure hardware if the context has changed. */ 130 if (fimc->m2m.ctx != ctx) { 131 ctx->state |= FIMC_PARAMS; 132 fimc->m2m.ctx = ctx; 133 } 134 135 if (ctx->state & FIMC_PARAMS) { 136 fimc_set_yuv_order(ctx); 137 fimc_hw_set_input_path(ctx); 138 fimc_hw_set_in_dma(ctx); 139 ret = fimc_set_scaler_info(ctx); 140 if (ret) 141 goto dma_unlock; 142 fimc_hw_set_prescaler(ctx); 143 fimc_hw_set_mainscaler(ctx); 144 fimc_hw_set_target_format(ctx); 145 fimc_hw_set_rotation(ctx); 146 fimc_hw_set_effect(ctx); 147 fimc_hw_set_out_dma(ctx); 148 if (fimc->drv_data->alpha_color) 149 fimc_hw_set_rgb_alpha(ctx); 150 fimc_hw_set_output_path(ctx); 151 } 152 fimc_hw_set_input_addr(fimc, &sf->addr); 153 fimc_hw_set_output_addr(fimc, &df->addr, -1); 154 155 fimc_activate_capture(ctx); 156 ctx->state &= (FIMC_CTX_M2M | FIMC_CTX_CAP); 157 fimc_hw_activate_input_dma(fimc, true); 158 159 dma_unlock: 160 spin_unlock_irqrestore(&fimc->slock, flags); 161 } 162 163 static void fimc_job_abort(void *priv) 164 { 165 fimc_m2m_shutdown(priv); 166 } 167 168 static int fimc_queue_setup(struct vb2_queue *vq, 169 unsigned int *num_buffers, unsigned int *num_planes, 170 unsigned int sizes[], struct device *alloc_devs[]) 171 { 172 struct fimc_ctx *ctx = vb2_get_drv_priv(vq); 173 const struct fimc_frame *f; 174 int i; 175 176 f = ctx_get_frame(ctx, vq->type); 177 if (IS_ERR(f)) 178 return PTR_ERR(f); 179 /* 180 * Return number of non-contiguous planes (plane buffers) 181 * depending on the configured color format. 182 */ 183 if (!f->fmt) 184 return -EINVAL; 185 186 *num_planes = f->fmt->memplanes; 187 for (i = 0; i < f->fmt->memplanes; i++) 188 sizes[i] = f->payload[i]; 189 return 0; 190 } 191 192 static int fimc_buf_prepare(struct vb2_buffer *vb) 193 { 194 struct fimc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); 195 const struct fimc_frame *frame; 196 int i; 197 198 frame = ctx_get_frame(ctx, vb->vb2_queue->type); 199 if (IS_ERR(frame)) 200 return PTR_ERR(frame); 201 202 for (i = 0; i < frame->fmt->memplanes; i++) 203 vb2_set_plane_payload(vb, i, frame->payload[i]); 204 205 return 0; 206 } 207 208 static void fimc_buf_queue(struct vb2_buffer *vb) 209 { 210 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 211 struct fimc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); 212 v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); 213 } 214 215 static const struct vb2_ops fimc_qops = { 216 .queue_setup = fimc_queue_setup, 217 .buf_prepare = fimc_buf_prepare, 218 .buf_queue = fimc_buf_queue, 219 .stop_streaming = stop_streaming, 220 .start_streaming = start_streaming, 221 }; 222 223 /* 224 * V4L2 ioctl handlers 225 */ 226 static int fimc_m2m_querycap(struct file *file, void *fh, 227 struct v4l2_capability *cap) 228 { 229 struct fimc_dev *fimc = video_drvdata(file); 230 231 __fimc_vidioc_querycap(&fimc->pdev->dev, cap); 232 return 0; 233 } 234 235 static int fimc_m2m_enum_fmt(struct file *file, void *priv, 236 struct v4l2_fmtdesc *f) 237 { 238 const struct fimc_fmt *fmt; 239 240 fmt = fimc_find_format(NULL, NULL, get_m2m_fmt_flags(f->type), 241 f->index); 242 if (!fmt) 243 return -EINVAL; 244 245 f->pixelformat = fmt->fourcc; 246 return 0; 247 } 248 249 static int fimc_m2m_g_fmt_mplane(struct file *file, void *fh, 250 struct v4l2_format *f) 251 { 252 struct fimc_ctx *ctx = fh_to_ctx(fh); 253 const struct fimc_frame *frame = ctx_get_frame(ctx, f->type); 254 255 if (IS_ERR(frame)) 256 return PTR_ERR(frame); 257 258 __fimc_get_format(frame, f); 259 return 0; 260 } 261 262 static int fimc_try_fmt_mplane(struct fimc_ctx *ctx, struct v4l2_format *f) 263 { 264 struct fimc_dev *fimc = ctx->fimc_dev; 265 const struct fimc_variant *variant = fimc->variant; 266 struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; 267 const struct fimc_fmt *fmt; 268 u32 max_w, mod_x, mod_y; 269 270 if (!IS_M2M(f->type)) 271 return -EINVAL; 272 273 fmt = fimc_find_format(&pix->pixelformat, NULL, 274 get_m2m_fmt_flags(f->type), 0); 275 if (WARN(fmt == NULL, "Pixel format lookup failed")) 276 return -EINVAL; 277 278 if (pix->field == V4L2_FIELD_ANY) 279 pix->field = V4L2_FIELD_NONE; 280 else if (pix->field != V4L2_FIELD_NONE) 281 return -EINVAL; 282 283 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { 284 max_w = variant->pix_limit->scaler_dis_w; 285 mod_x = ffs(variant->min_inp_pixsize) - 1; 286 } else { 287 max_w = variant->pix_limit->out_rot_dis_w; 288 mod_x = ffs(variant->min_out_pixsize) - 1; 289 } 290 291 if (tiled_fmt(fmt)) { 292 mod_x = 6; /* 64 x 32 pixels tile */ 293 mod_y = 5; 294 } else { 295 if (variant->min_vsize_align == 1) 296 mod_y = fimc_fmt_is_rgb(fmt->color) ? 0 : 1; 297 else 298 mod_y = ffs(variant->min_vsize_align) - 1; 299 } 300 301 v4l_bound_align_image(&pix->width, 16, max_w, mod_x, 302 &pix->height, 8, variant->pix_limit->scaler_dis_w, mod_y, 0); 303 304 fimc_adjust_mplane_format(fmt, pix->width, pix->height, &f->fmt.pix_mp); 305 return 0; 306 } 307 308 static int fimc_m2m_try_fmt_mplane(struct file *file, void *fh, 309 struct v4l2_format *f) 310 { 311 struct fimc_ctx *ctx = fh_to_ctx(fh); 312 return fimc_try_fmt_mplane(ctx, f); 313 } 314 315 static void __set_frame_format(struct fimc_frame *frame, 316 const struct fimc_fmt *fmt, 317 const struct v4l2_pix_format_mplane *pixm) 318 { 319 int i; 320 321 for (i = 0; i < fmt->memplanes; i++) { 322 frame->bytesperline[i] = pixm->plane_fmt[i].bytesperline; 323 frame->payload[i] = pixm->plane_fmt[i].sizeimage; 324 } 325 326 frame->f_width = pixm->width; 327 frame->f_height = pixm->height; 328 frame->o_width = pixm->width; 329 frame->o_height = pixm->height; 330 frame->width = pixm->width; 331 frame->height = pixm->height; 332 frame->offs_h = 0; 333 frame->offs_v = 0; 334 frame->fmt = fmt; 335 } 336 337 static int fimc_m2m_s_fmt_mplane(struct file *file, void *fh, 338 struct v4l2_format *f) 339 { 340 struct fimc_ctx *ctx = fh_to_ctx(fh); 341 struct fimc_dev *fimc = ctx->fimc_dev; 342 const struct fimc_fmt *fmt; 343 struct vb2_queue *vq; 344 struct fimc_frame *frame; 345 int ret; 346 347 ret = fimc_try_fmt_mplane(ctx, f); 348 if (ret) 349 return ret; 350 351 vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); 352 353 if (vb2_is_busy(vq)) { 354 v4l2_err(&fimc->m2m.vfd, "queue (%d) busy\n", f->type); 355 return -EBUSY; 356 } 357 358 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) 359 frame = &ctx->s_frame; 360 else 361 frame = &ctx->d_frame; 362 363 fmt = fimc_find_format(&f->fmt.pix_mp.pixelformat, NULL, 364 get_m2m_fmt_flags(f->type), 0); 365 if (!fmt) 366 return -EINVAL; 367 368 __set_frame_format(frame, fmt, &f->fmt.pix_mp); 369 370 /* Update RGB Alpha control state and value range */ 371 fimc_alpha_ctrl_update(ctx); 372 373 return 0; 374 } 375 376 static int fimc_m2m_g_selection(struct file *file, void *fh, 377 struct v4l2_selection *s) 378 { 379 struct fimc_ctx *ctx = fh_to_ctx(fh); 380 const struct fimc_frame *frame; 381 382 frame = ctx_get_frame(ctx, s->type); 383 if (IS_ERR(frame)) 384 return PTR_ERR(frame); 385 386 switch (s->target) { 387 case V4L2_SEL_TGT_CROP: 388 case V4L2_SEL_TGT_CROP_DEFAULT: 389 case V4L2_SEL_TGT_CROP_BOUNDS: 390 if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) 391 return -EINVAL; 392 break; 393 case V4L2_SEL_TGT_COMPOSE: 394 case V4L2_SEL_TGT_COMPOSE_DEFAULT: 395 case V4L2_SEL_TGT_COMPOSE_BOUNDS: 396 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 397 return -EINVAL; 398 break; 399 default: 400 return -EINVAL; 401 } 402 403 switch (s->target) { 404 case V4L2_SEL_TGT_CROP: 405 case V4L2_SEL_TGT_COMPOSE: 406 s->r.left = frame->offs_h; 407 s->r.top = frame->offs_v; 408 s->r.width = frame->width; 409 s->r.height = frame->height; 410 break; 411 case V4L2_SEL_TGT_CROP_DEFAULT: 412 case V4L2_SEL_TGT_CROP_BOUNDS: 413 case V4L2_SEL_TGT_COMPOSE_DEFAULT: 414 case V4L2_SEL_TGT_COMPOSE_BOUNDS: 415 s->r.left = 0; 416 s->r.top = 0; 417 s->r.width = frame->o_width; 418 s->r.height = frame->o_height; 419 break; 420 default: 421 return -EINVAL; 422 } 423 return 0; 424 } 425 426 static int fimc_m2m_try_selection(struct fimc_ctx *ctx, 427 struct v4l2_selection *s) 428 { 429 struct fimc_dev *fimc = ctx->fimc_dev; 430 const struct fimc_frame *f; 431 u32 min_size, halign, depth = 0; 432 int i; 433 434 if (s->r.top < 0 || s->r.left < 0) { 435 v4l2_err(&fimc->m2m.vfd, 436 "doesn't support negative values for top & left\n"); 437 return -EINVAL; 438 } 439 if (s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { 440 f = &ctx->d_frame; 441 if (s->target != V4L2_SEL_TGT_COMPOSE) 442 return -EINVAL; 443 } else if (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { 444 f = &ctx->s_frame; 445 if (s->target != V4L2_SEL_TGT_CROP) 446 return -EINVAL; 447 } else { 448 return -EINVAL; 449 } 450 451 min_size = (f == &ctx->s_frame) ? 452 fimc->variant->min_inp_pixsize : fimc->variant->min_out_pixsize; 453 454 /* Get pixel alignment constraints. */ 455 if (fimc->variant->min_vsize_align == 1) 456 halign = fimc_fmt_is_rgb(f->fmt->color) ? 0 : 1; 457 else 458 halign = ffs(fimc->variant->min_vsize_align) - 1; 459 460 for (i = 0; i < f->fmt->memplanes; i++) 461 depth += f->fmt->depth[i]; 462 463 v4l_bound_align_image(&s->r.width, min_size, f->o_width, 464 ffs(min_size) - 1, 465 &s->r.height, min_size, f->o_height, 466 halign, 64/(ALIGN(depth, 8))); 467 468 /* adjust left/top if cropping rectangle is out of bounds */ 469 if (s->r.left + s->r.width > f->o_width) 470 s->r.left = f->o_width - s->r.width; 471 if (s->r.top + s->r.height > f->o_height) 472 s->r.top = f->o_height - s->r.height; 473 474 s->r.left = round_down(s->r.left, min_size); 475 s->r.top = round_down(s->r.top, fimc->variant->hor_offs_align); 476 477 dbg("l:%d, t:%d, w:%d, h:%d, f_w: %d, f_h: %d", 478 s->r.left, s->r.top, s->r.width, s->r.height, 479 f->f_width, f->f_height); 480 481 return 0; 482 } 483 484 static int fimc_m2m_s_selection(struct file *file, void *fh, 485 struct v4l2_selection *s) 486 { 487 struct fimc_ctx *ctx = fh_to_ctx(fh); 488 struct fimc_dev *fimc = ctx->fimc_dev; 489 struct fimc_frame *f; 490 int ret; 491 492 ret = fimc_m2m_try_selection(ctx, s); 493 if (ret) 494 return ret; 495 496 f = (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) ? 497 &ctx->s_frame : &ctx->d_frame; 498 499 /* Check to see if scaling ratio is within supported range */ 500 if (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { 501 ret = fimc_check_scaler_ratio(ctx, s->r.width, 502 s->r.height, ctx->d_frame.width, 503 ctx->d_frame.height, ctx->rotation); 504 } else { 505 ret = fimc_check_scaler_ratio(ctx, ctx->s_frame.width, 506 ctx->s_frame.height, s->r.width, 507 s->r.height, ctx->rotation); 508 } 509 if (ret) { 510 v4l2_err(&fimc->m2m.vfd, "Out of scaler range\n"); 511 return -EINVAL; 512 } 513 514 f->offs_h = s->r.left; 515 f->offs_v = s->r.top; 516 f->width = s->r.width; 517 f->height = s->r.height; 518 519 fimc_ctx_state_set(FIMC_PARAMS, ctx); 520 521 return 0; 522 } 523 524 static const struct v4l2_ioctl_ops fimc_m2m_ioctl_ops = { 525 .vidioc_querycap = fimc_m2m_querycap, 526 .vidioc_enum_fmt_vid_cap = fimc_m2m_enum_fmt, 527 .vidioc_enum_fmt_vid_out = fimc_m2m_enum_fmt, 528 .vidioc_g_fmt_vid_cap_mplane = fimc_m2m_g_fmt_mplane, 529 .vidioc_g_fmt_vid_out_mplane = fimc_m2m_g_fmt_mplane, 530 .vidioc_try_fmt_vid_cap_mplane = fimc_m2m_try_fmt_mplane, 531 .vidioc_try_fmt_vid_out_mplane = fimc_m2m_try_fmt_mplane, 532 .vidioc_s_fmt_vid_cap_mplane = fimc_m2m_s_fmt_mplane, 533 .vidioc_s_fmt_vid_out_mplane = fimc_m2m_s_fmt_mplane, 534 .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, 535 .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, 536 .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, 537 .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, 538 .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, 539 .vidioc_streamon = v4l2_m2m_ioctl_streamon, 540 .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, 541 .vidioc_g_selection = fimc_m2m_g_selection, 542 .vidioc_s_selection = fimc_m2m_s_selection, 543 544 }; 545 546 static int queue_init(void *priv, struct vb2_queue *src_vq, 547 struct vb2_queue *dst_vq) 548 { 549 struct fimc_ctx *ctx = priv; 550 int ret; 551 552 src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 553 src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; 554 src_vq->drv_priv = ctx; 555 src_vq->ops = &fimc_qops; 556 src_vq->mem_ops = &vb2_dma_contig_memops; 557 src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); 558 src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; 559 src_vq->lock = &ctx->fimc_dev->lock; 560 src_vq->dev = &ctx->fimc_dev->pdev->dev; 561 562 ret = vb2_queue_init(src_vq); 563 if (ret) 564 return ret; 565 566 dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 567 dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; 568 dst_vq->drv_priv = ctx; 569 dst_vq->ops = &fimc_qops; 570 dst_vq->mem_ops = &vb2_dma_contig_memops; 571 dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); 572 dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; 573 dst_vq->lock = &ctx->fimc_dev->lock; 574 dst_vq->dev = &ctx->fimc_dev->pdev->dev; 575 576 return vb2_queue_init(dst_vq); 577 } 578 579 static int fimc_m2m_set_default_format(struct fimc_ctx *ctx) 580 { 581 struct v4l2_pix_format_mplane pixm = { 582 .pixelformat = V4L2_PIX_FMT_RGB32, 583 .width = 800, 584 .height = 600, 585 .plane_fmt[0] = { 586 .bytesperline = 800 * 4, 587 .sizeimage = 800 * 4 * 600, 588 }, 589 }; 590 const struct fimc_fmt *fmt; 591 592 fmt = fimc_find_format(&pixm.pixelformat, NULL, FMT_FLAGS_M2M, 0); 593 if (!fmt) 594 return -EINVAL; 595 596 __set_frame_format(&ctx->s_frame, fmt, &pixm); 597 __set_frame_format(&ctx->d_frame, fmt, &pixm); 598 599 return 0; 600 } 601 602 static int fimc_m2m_open(struct file *file) 603 { 604 struct fimc_dev *fimc = video_drvdata(file); 605 struct fimc_ctx *ctx; 606 int ret = -EBUSY; 607 608 pr_debug("pid: %d, state: %#lx\n", task_pid_nr(current), fimc->state); 609 610 if (mutex_lock_interruptible(&fimc->lock)) 611 return -ERESTARTSYS; 612 /* 613 * Don't allow simultaneous open() of the mem-to-mem and the 614 * capture video node that belong to same FIMC IP instance. 615 */ 616 if (test_bit(ST_CAPT_BUSY, &fimc->state)) 617 goto unlock; 618 619 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 620 if (!ctx) { 621 ret = -ENOMEM; 622 goto unlock; 623 } 624 v4l2_fh_init(&ctx->fh, &fimc->m2m.vfd); 625 ctx->fimc_dev = fimc; 626 627 /* Default color format */ 628 ctx->s_frame.fmt = fimc_get_format(0); 629 ctx->d_frame.fmt = fimc_get_format(0); 630 631 ret = fimc_ctrls_create(ctx); 632 if (ret) 633 goto error_fh; 634 635 /* Use separate control handler per file handle */ 636 ctx->fh.ctrl_handler = &ctx->ctrls.handler; 637 file->private_data = &ctx->fh; 638 v4l2_fh_add(&ctx->fh); 639 640 /* Setup the device context for memory-to-memory mode */ 641 ctx->state = FIMC_CTX_M2M; 642 ctx->flags = 0; 643 ctx->in_path = FIMC_IO_DMA; 644 ctx->out_path = FIMC_IO_DMA; 645 ctx->scaler.enabled = 1; 646 647 ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(fimc->m2m.m2m_dev, ctx, queue_init); 648 if (IS_ERR(ctx->fh.m2m_ctx)) { 649 ret = PTR_ERR(ctx->fh.m2m_ctx); 650 goto error_c; 651 } 652 653 if (fimc->m2m.refcnt++ == 0) 654 set_bit(ST_M2M_RUN, &fimc->state); 655 656 ret = fimc_m2m_set_default_format(ctx); 657 if (ret < 0) 658 goto error_m2m_ctx; 659 660 mutex_unlock(&fimc->lock); 661 return 0; 662 663 error_m2m_ctx: 664 v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); 665 error_c: 666 fimc_ctrls_delete(ctx); 667 v4l2_fh_del(&ctx->fh); 668 error_fh: 669 v4l2_fh_exit(&ctx->fh); 670 kfree(ctx); 671 unlock: 672 mutex_unlock(&fimc->lock); 673 return ret; 674 } 675 676 static int fimc_m2m_release(struct file *file) 677 { 678 struct fimc_ctx *ctx = fh_to_ctx(file->private_data); 679 struct fimc_dev *fimc = ctx->fimc_dev; 680 681 dbg("pid: %d, state: 0x%lx, refcnt= %d", 682 task_pid_nr(current), fimc->state, fimc->m2m.refcnt); 683 684 mutex_lock(&fimc->lock); 685 686 v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); 687 fimc_ctrls_delete(ctx); 688 v4l2_fh_del(&ctx->fh); 689 v4l2_fh_exit(&ctx->fh); 690 691 if (--fimc->m2m.refcnt <= 0) 692 clear_bit(ST_M2M_RUN, &fimc->state); 693 kfree(ctx); 694 695 mutex_unlock(&fimc->lock); 696 return 0; 697 } 698 699 static const struct v4l2_file_operations fimc_m2m_fops = { 700 .owner = THIS_MODULE, 701 .open = fimc_m2m_open, 702 .release = fimc_m2m_release, 703 .poll = v4l2_m2m_fop_poll, 704 .unlocked_ioctl = video_ioctl2, 705 .mmap = v4l2_m2m_fop_mmap, 706 }; 707 708 static const struct v4l2_m2m_ops m2m_ops = { 709 .device_run = fimc_device_run, 710 .job_abort = fimc_job_abort, 711 }; 712 713 int fimc_register_m2m_device(struct fimc_dev *fimc, 714 struct v4l2_device *v4l2_dev) 715 { 716 struct video_device *vfd = &fimc->m2m.vfd; 717 int ret; 718 719 fimc->v4l2_dev = v4l2_dev; 720 721 memset(vfd, 0, sizeof(*vfd)); 722 vfd->fops = &fimc_m2m_fops; 723 vfd->ioctl_ops = &fimc_m2m_ioctl_ops; 724 vfd->v4l2_dev = v4l2_dev; 725 vfd->minor = -1; 726 vfd->release = video_device_release_empty; 727 vfd->lock = &fimc->lock; 728 vfd->vfl_dir = VFL_DIR_M2M; 729 vfd->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M_MPLANE; 730 set_bit(V4L2_FL_QUIRK_INVERTED_CROP, &vfd->flags); 731 732 snprintf(vfd->name, sizeof(vfd->name), "fimc.%d.m2m", fimc->id); 733 video_set_drvdata(vfd, fimc); 734 735 fimc->m2m.m2m_dev = v4l2_m2m_init(&m2m_ops); 736 if (IS_ERR(fimc->m2m.m2m_dev)) { 737 v4l2_err(v4l2_dev, "failed to initialize v4l2-m2m device\n"); 738 return PTR_ERR(fimc->m2m.m2m_dev); 739 } 740 741 ret = media_entity_pads_init(&vfd->entity, 0, NULL); 742 if (ret) 743 goto err_me; 744 745 ret = video_register_device(vfd, VFL_TYPE_VIDEO, -1); 746 if (ret) 747 goto err_vd; 748 749 v4l2_info(v4l2_dev, "Registered %s as /dev/%s\n", 750 vfd->name, video_device_node_name(vfd)); 751 return 0; 752 753 err_vd: 754 media_entity_cleanup(&vfd->entity); 755 err_me: 756 v4l2_m2m_release(fimc->m2m.m2m_dev); 757 return ret; 758 } 759 760 void fimc_unregister_m2m_device(struct fimc_dev *fimc) 761 { 762 if (!fimc) 763 return; 764 765 if (fimc->m2m.m2m_dev) 766 v4l2_m2m_release(fimc->m2m.m2m_dev); 767 768 if (video_is_registered(&fimc->m2m.vfd)) { 769 video_unregister_device(&fimc->m2m.vfd); 770 media_entity_cleanup(&fimc->m2m.vfd.entity); 771 } 772 } 773