Lines Matching +full:top +full:- +full:left

1 // SPDX-License-Identifier: GPL-2.0-or-later
5 * Copyright (C) 2012 - 2013 Samsung Electronics Co., Ltd.
22 #include <media/v4l2-ioctl.h>
23 #include <media/videobuf2-v4l2.h>
24 #include <media/videobuf2-dma-contig.h>
27 #include "fimc-core.h"
28 #include "fimc-reg.h"
29 #include "media-dev.h"
43 if (!ctx || !ctx->fh.m2m_ctx) in fimc_m2m_job_finish()
46 src_vb = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); in fimc_m2m_job_finish()
47 dst_vb = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); in fimc_m2m_job_finish()
54 v4l2_m2m_job_finish(ctx->fimc_dev->m2m.m2m_dev, in fimc_m2m_job_finish()
55 ctx->fh.m2m_ctx); in fimc_m2m_job_finish()
61 struct fimc_dev *fimc = ctx->fimc_dev; in fimc_m2m_shutdown()
68 wait_event_timeout(fimc->irq_queue, in fimc_m2m_shutdown()
75 struct fimc_ctx *ctx = q->drv_priv; in start_streaming()
77 return pm_runtime_resume_and_get(&ctx->fimc_dev->pdev->dev); in start_streaming()
82 struct fimc_ctx *ctx = q->drv_priv; in stop_streaming()
86 pm_runtime_put(&ctx->fimc_dev->pdev->dev); in stop_streaming()
101 fimc = ctx->fimc_dev; in fimc_device_run()
102 spin_lock_irqsave(&fimc->slock, flags); in fimc_device_run()
104 set_bit(ST_M2M_PEND, &fimc->state); in fimc_device_run()
105 sf = &ctx->s_frame; in fimc_device_run()
106 df = &ctx->d_frame; in fimc_device_run()
108 if (ctx->state & FIMC_PARAMS) { in fimc_device_run()
114 src_vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); in fimc_device_run()
115 ret = fimc_prepare_addr(ctx, &src_vb->vb2_buf, sf, &sf->addr); in fimc_device_run()
119 dst_vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); in fimc_device_run()
120 ret = fimc_prepare_addr(ctx, &dst_vb->vb2_buf, df, &df->addr); in fimc_device_run()
124 dst_vb->vb2_buf.timestamp = src_vb->vb2_buf.timestamp; in fimc_device_run()
125 dst_vb->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; in fimc_device_run()
126 dst_vb->flags |= in fimc_device_run()
127 src_vb->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK; in fimc_device_run()
130 if (fimc->m2m.ctx != ctx) { in fimc_device_run()
131 ctx->state |= FIMC_PARAMS; in fimc_device_run()
132 fimc->m2m.ctx = ctx; in fimc_device_run()
135 if (ctx->state & FIMC_PARAMS) { in fimc_device_run()
148 if (fimc->drv_data->alpha_color) in fimc_device_run()
152 fimc_hw_set_input_addr(fimc, &sf->addr); in fimc_device_run()
153 fimc_hw_set_output_addr(fimc, &df->addr, -1); in fimc_device_run()
156 ctx->state &= (FIMC_CTX_M2M | FIMC_CTX_CAP); in fimc_device_run()
160 spin_unlock_irqrestore(&fimc->slock, flags); in fimc_device_run()
176 f = ctx_get_frame(ctx, vq->type); in fimc_queue_setup()
180 * Return number of non-contiguous planes (plane buffers) in fimc_queue_setup()
183 if (!f->fmt) in fimc_queue_setup()
184 return -EINVAL; in fimc_queue_setup()
186 *num_planes = f->fmt->memplanes; in fimc_queue_setup()
187 for (i = 0; i < f->fmt->memplanes; i++) in fimc_queue_setup()
188 sizes[i] = f->payload[i]; in fimc_queue_setup()
194 struct fimc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); in fimc_buf_prepare()
198 frame = ctx_get_frame(ctx, vb->vb2_queue->type); in fimc_buf_prepare()
202 for (i = 0; i < frame->fmt->memplanes; i++) in fimc_buf_prepare()
203 vb2_set_plane_payload(vb, i, frame->payload[i]); in fimc_buf_prepare()
211 struct fimc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); in fimc_buf_queue()
212 v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); in fimc_buf_queue()
233 __fimc_vidioc_querycap(&fimc->pdev->dev, cap); in fimc_m2m_querycap()
242 fmt = fimc_find_format(NULL, NULL, get_m2m_fmt_flags(f->type), in fimc_m2m_enum_fmt()
243 f->index); in fimc_m2m_enum_fmt()
245 return -EINVAL; in fimc_m2m_enum_fmt()
247 f->pixelformat = fmt->fourcc; in fimc_m2m_enum_fmt()
255 struct fimc_frame *frame = ctx_get_frame(ctx, f->type); in fimc_m2m_g_fmt_mplane()
266 struct fimc_dev *fimc = ctx->fimc_dev; in fimc_try_fmt_mplane()
267 const struct fimc_variant *variant = fimc->variant; in fimc_try_fmt_mplane()
268 struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; in fimc_try_fmt_mplane()
272 if (!IS_M2M(f->type)) in fimc_try_fmt_mplane()
273 return -EINVAL; in fimc_try_fmt_mplane()
275 fmt = fimc_find_format(&pix->pixelformat, NULL, in fimc_try_fmt_mplane()
276 get_m2m_fmt_flags(f->type), 0); in fimc_try_fmt_mplane()
278 return -EINVAL; in fimc_try_fmt_mplane()
280 if (pix->field == V4L2_FIELD_ANY) in fimc_try_fmt_mplane()
281 pix->field = V4L2_FIELD_NONE; in fimc_try_fmt_mplane()
282 else if (pix->field != V4L2_FIELD_NONE) in fimc_try_fmt_mplane()
283 return -EINVAL; in fimc_try_fmt_mplane()
285 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { in fimc_try_fmt_mplane()
286 max_w = variant->pix_limit->scaler_dis_w; in fimc_try_fmt_mplane()
287 mod_x = ffs(variant->min_inp_pixsize) - 1; in fimc_try_fmt_mplane()
289 max_w = variant->pix_limit->out_rot_dis_w; in fimc_try_fmt_mplane()
290 mod_x = ffs(variant->min_out_pixsize) - 1; in fimc_try_fmt_mplane()
297 if (variant->min_vsize_align == 1) in fimc_try_fmt_mplane()
298 mod_y = fimc_fmt_is_rgb(fmt->color) ? 0 : 1; in fimc_try_fmt_mplane()
300 mod_y = ffs(variant->min_vsize_align) - 1; in fimc_try_fmt_mplane()
303 v4l_bound_align_image(&pix->width, 16, max_w, mod_x, in fimc_try_fmt_mplane()
304 &pix->height, 8, variant->pix_limit->scaler_dis_w, mod_y, 0); in fimc_try_fmt_mplane()
306 fimc_adjust_mplane_format(fmt, pix->width, pix->height, &f->fmt.pix_mp); in fimc_try_fmt_mplane()
322 for (i = 0; i < fmt->memplanes; i++) { in __set_frame_format()
323 frame->bytesperline[i] = pixm->plane_fmt[i].bytesperline; in __set_frame_format()
324 frame->payload[i] = pixm->plane_fmt[i].sizeimage; in __set_frame_format()
327 frame->f_width = pixm->width; in __set_frame_format()
328 frame->f_height = pixm->height; in __set_frame_format()
329 frame->o_width = pixm->width; in __set_frame_format()
330 frame->o_height = pixm->height; in __set_frame_format()
331 frame->width = pixm->width; in __set_frame_format()
332 frame->height = pixm->height; in __set_frame_format()
333 frame->offs_h = 0; in __set_frame_format()
334 frame->offs_v = 0; in __set_frame_format()
335 frame->fmt = fmt; in __set_frame_format()
342 struct fimc_dev *fimc = ctx->fimc_dev; in fimc_m2m_s_fmt_mplane()
352 vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); in fimc_m2m_s_fmt_mplane()
355 v4l2_err(&fimc->m2m.vfd, "queue (%d) busy\n", f->type); in fimc_m2m_s_fmt_mplane()
356 return -EBUSY; in fimc_m2m_s_fmt_mplane()
359 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) in fimc_m2m_s_fmt_mplane()
360 frame = &ctx->s_frame; in fimc_m2m_s_fmt_mplane()
362 frame = &ctx->d_frame; in fimc_m2m_s_fmt_mplane()
364 fmt = fimc_find_format(&f->fmt.pix_mp.pixelformat, NULL, in fimc_m2m_s_fmt_mplane()
365 get_m2m_fmt_flags(f->type), 0); in fimc_m2m_s_fmt_mplane()
367 return -EINVAL; in fimc_m2m_s_fmt_mplane()
369 __set_frame_format(frame, fmt, &f->fmt.pix_mp); in fimc_m2m_s_fmt_mplane()
383 frame = ctx_get_frame(ctx, s->type); in fimc_m2m_g_selection()
387 switch (s->target) { in fimc_m2m_g_selection()
391 if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) in fimc_m2m_g_selection()
392 return -EINVAL; in fimc_m2m_g_selection()
397 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) in fimc_m2m_g_selection()
398 return -EINVAL; in fimc_m2m_g_selection()
401 return -EINVAL; in fimc_m2m_g_selection()
404 switch (s->target) { in fimc_m2m_g_selection()
407 s->r.left = frame->offs_h; in fimc_m2m_g_selection()
408 s->r.top = frame->offs_v; in fimc_m2m_g_selection()
409 s->r.width = frame->width; in fimc_m2m_g_selection()
410 s->r.height = frame->height; in fimc_m2m_g_selection()
416 s->r.left = 0; in fimc_m2m_g_selection()
417 s->r.top = 0; in fimc_m2m_g_selection()
418 s->r.width = frame->o_width; in fimc_m2m_g_selection()
419 s->r.height = frame->o_height; in fimc_m2m_g_selection()
422 return -EINVAL; in fimc_m2m_g_selection()
430 struct fimc_dev *fimc = ctx->fimc_dev; in fimc_m2m_try_selection()
435 if (s->r.top < 0 || s->r.left < 0) { in fimc_m2m_try_selection()
436 v4l2_err(&fimc->m2m.vfd, in fimc_m2m_try_selection()
437 "doesn't support negative values for top & left\n"); in fimc_m2m_try_selection()
438 return -EINVAL; in fimc_m2m_try_selection()
440 if (s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { in fimc_m2m_try_selection()
441 f = &ctx->d_frame; in fimc_m2m_try_selection()
442 if (s->target != V4L2_SEL_TGT_COMPOSE) in fimc_m2m_try_selection()
443 return -EINVAL; in fimc_m2m_try_selection()
444 } else if (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { in fimc_m2m_try_selection()
445 f = &ctx->s_frame; in fimc_m2m_try_selection()
446 if (s->target != V4L2_SEL_TGT_CROP) in fimc_m2m_try_selection()
447 return -EINVAL; in fimc_m2m_try_selection()
449 return -EINVAL; in fimc_m2m_try_selection()
452 min_size = (f == &ctx->s_frame) ? in fimc_m2m_try_selection()
453 fimc->variant->min_inp_pixsize : fimc->variant->min_out_pixsize; in fimc_m2m_try_selection()
456 if (fimc->variant->min_vsize_align == 1) in fimc_m2m_try_selection()
457 halign = fimc_fmt_is_rgb(f->fmt->color) ? 0 : 1; in fimc_m2m_try_selection()
459 halign = ffs(fimc->variant->min_vsize_align) - 1; in fimc_m2m_try_selection()
461 for (i = 0; i < f->fmt->memplanes; i++) in fimc_m2m_try_selection()
462 depth += f->fmt->depth[i]; in fimc_m2m_try_selection()
464 v4l_bound_align_image(&s->r.width, min_size, f->o_width, in fimc_m2m_try_selection()
465 ffs(min_size) - 1, in fimc_m2m_try_selection()
466 &s->r.height, min_size, f->o_height, in fimc_m2m_try_selection()
469 /* adjust left/top if cropping rectangle is out of bounds */ in fimc_m2m_try_selection()
470 if (s->r.left + s->r.width > f->o_width) in fimc_m2m_try_selection()
471 s->r.left = f->o_width - s->r.width; in fimc_m2m_try_selection()
472 if (s->r.top + s->r.height > f->o_height) in fimc_m2m_try_selection()
473 s->r.top = f->o_height - s->r.height; in fimc_m2m_try_selection()
475 s->r.left = round_down(s->r.left, min_size); in fimc_m2m_try_selection()
476 s->r.top = round_down(s->r.top, fimc->variant->hor_offs_align); in fimc_m2m_try_selection()
479 s->r.left, s->r.top, s->r.width, s->r.height, in fimc_m2m_try_selection()
480 f->f_width, f->f_height); in fimc_m2m_try_selection()
489 struct fimc_dev *fimc = ctx->fimc_dev; in fimc_m2m_s_selection()
497 f = (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) ? in fimc_m2m_s_selection()
498 &ctx->s_frame : &ctx->d_frame; in fimc_m2m_s_selection()
501 if (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { in fimc_m2m_s_selection()
502 ret = fimc_check_scaler_ratio(ctx, s->r.width, in fimc_m2m_s_selection()
503 s->r.height, ctx->d_frame.width, in fimc_m2m_s_selection()
504 ctx->d_frame.height, ctx->rotation); in fimc_m2m_s_selection()
506 ret = fimc_check_scaler_ratio(ctx, ctx->s_frame.width, in fimc_m2m_s_selection()
507 ctx->s_frame.height, s->r.width, in fimc_m2m_s_selection()
508 s->r.height, ctx->rotation); in fimc_m2m_s_selection()
511 v4l2_err(&fimc->m2m.vfd, "Out of scaler range\n"); in fimc_m2m_s_selection()
512 return -EINVAL; in fimc_m2m_s_selection()
515 f->offs_h = s->r.left; in fimc_m2m_s_selection()
516 f->offs_v = s->r.top; in fimc_m2m_s_selection()
517 f->width = s->r.width; in fimc_m2m_s_selection()
518 f->height = s->r.height; in fimc_m2m_s_selection()
553 src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; in queue_init()
554 src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; in queue_init()
555 src_vq->drv_priv = ctx; in queue_init()
556 src_vq->ops = &fimc_qops; in queue_init()
557 src_vq->mem_ops = &vb2_dma_contig_memops; in queue_init()
558 src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); in queue_init()
559 src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; in queue_init()
560 src_vq->lock = &ctx->fimc_dev->lock; in queue_init()
561 src_vq->dev = &ctx->fimc_dev->pdev->dev; in queue_init()
567 dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; in queue_init()
568 dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; in queue_init()
569 dst_vq->drv_priv = ctx; in queue_init()
570 dst_vq->ops = &fimc_qops; in queue_init()
571 dst_vq->mem_ops = &vb2_dma_contig_memops; in queue_init()
572 dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); in queue_init()
573 dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; in queue_init()
574 dst_vq->lock = &ctx->fimc_dev->lock; in queue_init()
575 dst_vq->dev = &ctx->fimc_dev->pdev->dev; in queue_init()
595 return -EINVAL; in fimc_m2m_set_default_format()
597 __set_frame_format(&ctx->s_frame, fmt, &pixm); in fimc_m2m_set_default_format()
598 __set_frame_format(&ctx->d_frame, fmt, &pixm); in fimc_m2m_set_default_format()
607 int ret = -EBUSY; in fimc_m2m_open()
609 pr_debug("pid: %d, state: %#lx\n", task_pid_nr(current), fimc->state); in fimc_m2m_open()
611 if (mutex_lock_interruptible(&fimc->lock)) in fimc_m2m_open()
612 return -ERESTARTSYS; in fimc_m2m_open()
614 * Don't allow simultaneous open() of the mem-to-mem and the in fimc_m2m_open()
617 if (test_bit(ST_CAPT_BUSY, &fimc->state)) in fimc_m2m_open()
622 ret = -ENOMEM; in fimc_m2m_open()
625 v4l2_fh_init(&ctx->fh, &fimc->m2m.vfd); in fimc_m2m_open()
626 ctx->fimc_dev = fimc; in fimc_m2m_open()
629 ctx->s_frame.fmt = fimc_get_format(0); in fimc_m2m_open()
630 ctx->d_frame.fmt = fimc_get_format(0); in fimc_m2m_open()
637 ctx->fh.ctrl_handler = &ctx->ctrls.handler; in fimc_m2m_open()
638 file->private_data = &ctx->fh; in fimc_m2m_open()
639 v4l2_fh_add(&ctx->fh); in fimc_m2m_open()
641 /* Setup the device context for memory-to-memory mode */ in fimc_m2m_open()
642 ctx->state = FIMC_CTX_M2M; in fimc_m2m_open()
643 ctx->flags = 0; in fimc_m2m_open()
644 ctx->in_path = FIMC_IO_DMA; in fimc_m2m_open()
645 ctx->out_path = FIMC_IO_DMA; in fimc_m2m_open()
646 ctx->scaler.enabled = 1; in fimc_m2m_open()
648 ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(fimc->m2m.m2m_dev, ctx, queue_init); in fimc_m2m_open()
649 if (IS_ERR(ctx->fh.m2m_ctx)) { in fimc_m2m_open()
650 ret = PTR_ERR(ctx->fh.m2m_ctx); in fimc_m2m_open()
654 if (fimc->m2m.refcnt++ == 0) in fimc_m2m_open()
655 set_bit(ST_M2M_RUN, &fimc->state); in fimc_m2m_open()
661 mutex_unlock(&fimc->lock); in fimc_m2m_open()
665 v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); in fimc_m2m_open()
668 v4l2_fh_del(&ctx->fh); in fimc_m2m_open()
670 v4l2_fh_exit(&ctx->fh); in fimc_m2m_open()
673 mutex_unlock(&fimc->lock); in fimc_m2m_open()
679 struct fimc_ctx *ctx = fh_to_ctx(file->private_data); in fimc_m2m_release()
680 struct fimc_dev *fimc = ctx->fimc_dev; in fimc_m2m_release()
683 task_pid_nr(current), fimc->state, fimc->m2m.refcnt); in fimc_m2m_release()
685 mutex_lock(&fimc->lock); in fimc_m2m_release()
687 v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); in fimc_m2m_release()
689 v4l2_fh_del(&ctx->fh); in fimc_m2m_release()
690 v4l2_fh_exit(&ctx->fh); in fimc_m2m_release()
692 if (--fimc->m2m.refcnt <= 0) in fimc_m2m_release()
693 clear_bit(ST_M2M_RUN, &fimc->state); in fimc_m2m_release()
696 mutex_unlock(&fimc->lock); in fimc_m2m_release()
717 struct video_device *vfd = &fimc->m2m.vfd; in fimc_register_m2m_device()
720 fimc->v4l2_dev = v4l2_dev; in fimc_register_m2m_device()
723 vfd->fops = &fimc_m2m_fops; in fimc_register_m2m_device()
724 vfd->ioctl_ops = &fimc_m2m_ioctl_ops; in fimc_register_m2m_device()
725 vfd->v4l2_dev = v4l2_dev; in fimc_register_m2m_device()
726 vfd->minor = -1; in fimc_register_m2m_device()
727 vfd->release = video_device_release_empty; in fimc_register_m2m_device()
728 vfd->lock = &fimc->lock; in fimc_register_m2m_device()
729 vfd->vfl_dir = VFL_DIR_M2M; in fimc_register_m2m_device()
730 vfd->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M_MPLANE; in fimc_register_m2m_device()
731 set_bit(V4L2_FL_QUIRK_INVERTED_CROP, &vfd->flags); in fimc_register_m2m_device()
733 snprintf(vfd->name, sizeof(vfd->name), "fimc.%d.m2m", fimc->id); in fimc_register_m2m_device()
736 fimc->m2m.m2m_dev = v4l2_m2m_init(&m2m_ops); in fimc_register_m2m_device()
737 if (IS_ERR(fimc->m2m.m2m_dev)) { in fimc_register_m2m_device()
738 v4l2_err(v4l2_dev, "failed to initialize v4l2-m2m device\n"); in fimc_register_m2m_device()
739 return PTR_ERR(fimc->m2m.m2m_dev); in fimc_register_m2m_device()
742 ret = media_entity_pads_init(&vfd->entity, 0, NULL); in fimc_register_m2m_device()
746 ret = video_register_device(vfd, VFL_TYPE_VIDEO, -1); in fimc_register_m2m_device()
751 vfd->name, video_device_node_name(vfd)); in fimc_register_m2m_device()
755 media_entity_cleanup(&vfd->entity); in fimc_register_m2m_device()
757 v4l2_m2m_release(fimc->m2m.m2m_dev); in fimc_register_m2m_device()
766 if (fimc->m2m.m2m_dev) in fimc_unregister_m2m_device()
767 v4l2_m2m_release(fimc->m2m.m2m_dev); in fimc_unregister_m2m_device()
769 if (video_is_registered(&fimc->m2m.vfd)) { in fimc_unregister_m2m_device()
770 video_unregister_device(&fimc->m2m.vfd); in fimc_unregister_m2m_device()
771 media_entity_cleanup(&fimc->m2m.vfd.entity); in fimc_unregister_m2m_device()