Lines Matching +full:g +full:- +full:scaler

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (c) 2011 - 2012 Samsung Electronics Co., Ltd.
6 * Samsung EXYNOS5 SoC series G-Scaler driver
23 #include <media/v4l2-ioctl.h>
25 #include "gsc-core.h"
30 struct gsc_dev *gsc = ctx->gsc_dev; in gsc_m2m_ctx_stop_req()
33 curr_ctx = v4l2_m2m_get_curr_priv(gsc->m2m.m2m_dev); in gsc_m2m_ctx_stop_req()
38 ret = wait_event_timeout(gsc->irq_queue, in gsc_m2m_ctx_stop_req()
42 return ret == 0 ? -ETIMEDOUT : ret; in gsc_m2m_ctx_stop_req()
50 if ((ret == -ETIMEDOUT) || (ctx->state & GSC_CTX_ABORT)) { in __gsc_m2m_job_abort()
58 struct gsc_ctx *ctx = q->drv_priv; in gsc_m2m_start_streaming()
60 return pm_runtime_resume_and_get(&ctx->gsc_dev->pdev->dev); in gsc_m2m_start_streaming()
67 while (v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) > 0) { in __gsc_m2m_cleanup_queue()
68 src_vb = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); in __gsc_m2m_cleanup_queue()
72 while (v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) > 0) { in __gsc_m2m_cleanup_queue()
73 dst_vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); in __gsc_m2m_cleanup_queue()
80 struct gsc_ctx *ctx = q->drv_priv; in gsc_m2m_stop_streaming()
86 pm_runtime_put(&ctx->gsc_dev->pdev->dev); in gsc_m2m_stop_streaming()
93 if (!ctx || !ctx->m2m_ctx) in gsc_m2m_job_finish()
96 src_vb = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); in gsc_m2m_job_finish()
97 dst_vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); in gsc_m2m_job_finish()
100 dst_vb->vb2_buf.timestamp = src_vb->vb2_buf.timestamp; in gsc_m2m_job_finish()
101 dst_vb->timecode = src_vb->timecode; in gsc_m2m_job_finish()
102 dst_vb->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; in gsc_m2m_job_finish()
103 dst_vb->flags |= in gsc_m2m_job_finish()
104 src_vb->flags in gsc_m2m_job_finish()
110 v4l2_m2m_job_finish(ctx->gsc_dev->m2m.m2m_dev, in gsc_m2m_job_finish()
111 ctx->m2m_ctx); in gsc_m2m_job_finish()
126 s_frame = &ctx->s_frame; in gsc_get_bufs()
127 d_frame = &ctx->d_frame; in gsc_get_bufs()
129 src_vb = v4l2_m2m_next_src_buf(ctx->m2m_ctx); in gsc_get_bufs()
130 ret = gsc_prepare_addr(ctx, &src_vb->vb2_buf, s_frame, &s_frame->addr); in gsc_get_bufs()
134 dst_vb = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); in gsc_get_bufs()
135 ret = gsc_prepare_addr(ctx, &dst_vb->vb2_buf, d_frame, &d_frame->addr); in gsc_get_bufs()
139 dst_vb->vb2_buf.timestamp = src_vb->vb2_buf.timestamp; in gsc_get_bufs()
155 gsc = ctx->gsc_dev; in gsc_m2m_device_run()
156 spin_lock_irqsave(&gsc->slock, flags); in gsc_m2m_device_run()
158 set_bit(ST_M2M_PEND, &gsc->state); in gsc_m2m_device_run()
161 if (gsc->m2m.ctx != ctx) { in gsc_m2m_device_run()
162 pr_debug("gsc->m2m.ctx = 0x%p, current_ctx = 0x%p", in gsc_m2m_device_run()
163 gsc->m2m.ctx, ctx); in gsc_m2m_device_run()
164 ctx->state |= GSC_PARAMS; in gsc_m2m_device_run()
165 gsc->m2m.ctx = ctx; in gsc_m2m_device_run()
168 is_set = ctx->state & GSC_CTX_STOP_REQ; in gsc_m2m_device_run()
170 ctx->state &= ~GSC_CTX_STOP_REQ; in gsc_m2m_device_run()
171 ctx->state |= GSC_CTX_ABORT; in gsc_m2m_device_run()
172 wake_up(&gsc->irq_queue); in gsc_m2m_device_run()
182 gsc_set_prefbuf(gsc, &ctx->s_frame); in gsc_m2m_device_run()
183 gsc_hw_set_input_addr(gsc, &ctx->s_frame.addr, GSC_M2M_BUF_NUM); in gsc_m2m_device_run()
184 gsc_hw_set_output_addr(gsc, &ctx->d_frame.addr, GSC_M2M_BUF_NUM); in gsc_m2m_device_run()
186 if (ctx->state & GSC_PARAMS) { in gsc_m2m_device_run()
193 pr_err("Scaler setup error"); in gsc_m2m_device_run()
214 ctx->state &= ~GSC_PARAMS; in gsc_m2m_device_run()
217 spin_unlock_irqrestore(&gsc->slock, flags); in gsc_m2m_device_run()
221 ctx->state &= ~GSC_PARAMS; in gsc_m2m_device_run()
222 spin_unlock_irqrestore(&gsc->slock, flags); in gsc_m2m_device_run()
233 frame = ctx_get_frame(ctx, vq->type); in gsc_m2m_queue_setup()
237 if (!frame->fmt) in gsc_m2m_queue_setup()
238 return -EINVAL; in gsc_m2m_queue_setup()
240 *num_planes = frame->fmt->num_planes; in gsc_m2m_queue_setup()
241 for (i = 0; i < frame->fmt->num_planes; i++) in gsc_m2m_queue_setup()
242 sizes[i] = frame->payload[i]; in gsc_m2m_queue_setup()
248 struct gsc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); in gsc_m2m_buf_prepare()
252 frame = ctx_get_frame(ctx, vb->vb2_queue->type); in gsc_m2m_buf_prepare()
256 if (V4L2_TYPE_IS_CAPTURE(vb->vb2_queue->type)) { in gsc_m2m_buf_prepare()
257 for (i = 0; i < frame->fmt->num_planes; i++) in gsc_m2m_buf_prepare()
258 vb2_set_plane_payload(vb, i, frame->payload[i]); in gsc_m2m_buf_prepare()
267 struct gsc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); in gsc_m2m_buf_queue()
269 pr_debug("ctx: %p, ctx->state: 0x%x", ctx, ctx->state); in gsc_m2m_buf_queue()
271 if (ctx->m2m_ctx) in gsc_m2m_buf_queue()
272 v4l2_m2m_buf_queue(ctx->m2m_ctx, vbuf); in gsc_m2m_buf_queue()
288 strscpy(cap->driver, GSC_MODULE_NAME, sizeof(cap->driver)); in gsc_m2m_querycap()
289 strscpy(cap->card, GSC_MODULE_NAME " gscaler", sizeof(cap->card)); in gsc_m2m_querycap()
328 vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); in gsc_m2m_s_fmt_mplane()
331 pr_err("queue (%d) busy", f->type); in gsc_m2m_s_fmt_mplane()
332 return -EBUSY; in gsc_m2m_s_fmt_mplane()
335 if (V4L2_TYPE_IS_OUTPUT(f->type)) in gsc_m2m_s_fmt_mplane()
336 frame = &ctx->s_frame; in gsc_m2m_s_fmt_mplane()
338 frame = &ctx->d_frame; in gsc_m2m_s_fmt_mplane()
340 pix = &f->fmt.pix_mp; in gsc_m2m_s_fmt_mplane()
341 frame->fmt = find_fmt(&pix->pixelformat, NULL, 0); in gsc_m2m_s_fmt_mplane()
342 frame->colorspace = pix->colorspace; in gsc_m2m_s_fmt_mplane()
343 if (!frame->fmt) in gsc_m2m_s_fmt_mplane()
344 return -EINVAL; in gsc_m2m_s_fmt_mplane()
346 for (i = 0; i < frame->fmt->num_planes; i++) in gsc_m2m_s_fmt_mplane()
347 frame->payload[i] = pix->plane_fmt[i].sizeimage; in gsc_m2m_s_fmt_mplane()
349 gsc_set_frame_size(frame, pix->width, pix->height); in gsc_m2m_s_fmt_mplane()
351 if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) in gsc_m2m_s_fmt_mplane()
356 pr_debug("f_w: %d, f_h: %d", frame->f_width, frame->f_height); in gsc_m2m_s_fmt_mplane()
365 struct gsc_dev *gsc = ctx->gsc_dev; in gsc_m2m_reqbufs()
368 max_cnt = (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ? in gsc_m2m_reqbufs()
369 gsc->variant->in_buf_cnt : gsc->variant->out_buf_cnt; in gsc_m2m_reqbufs()
370 if (reqbufs->count > max_cnt) in gsc_m2m_reqbufs()
371 return -EINVAL; in gsc_m2m_reqbufs()
373 return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); in gsc_m2m_reqbufs()
380 return v4l2_m2m_expbuf(file, ctx->m2m_ctx, eb); in gsc_m2m_expbuf()
387 return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf); in gsc_m2m_querybuf()
394 return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); in gsc_m2m_qbuf()
401 return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); in gsc_m2m_dqbuf()
412 return -EINVAL; in gsc_m2m_streamon()
414 return -EINVAL; in gsc_m2m_streamon()
417 return v4l2_m2m_streamon(file, ctx->m2m_ctx, type); in gsc_m2m_streamon()
424 return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); in gsc_m2m_streamoff()
430 if (a->left < b->left || a->top < b->top) in is_rectangle_enclosed()
433 if (a->left + a->width > b->left + b->width) in is_rectangle_enclosed()
436 if (a->top + a->height > b->top + b->height) in is_rectangle_enclosed()
448 if ((s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && in gsc_m2m_g_selection()
449 (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)) in gsc_m2m_g_selection()
450 return -EINVAL; in gsc_m2m_g_selection()
452 frame = ctx_get_frame(ctx, s->type); in gsc_m2m_g_selection()
456 switch (s->target) { in gsc_m2m_g_selection()
461 s->r.left = 0; in gsc_m2m_g_selection()
462 s->r.top = 0; in gsc_m2m_g_selection()
463 s->r.width = frame->f_width; in gsc_m2m_g_selection()
464 s->r.height = frame->f_height; in gsc_m2m_g_selection()
469 s->r.left = frame->crop.left; in gsc_m2m_g_selection()
470 s->r.top = frame->crop.top; in gsc_m2m_g_selection()
471 s->r.width = frame->crop.width; in gsc_m2m_g_selection()
472 s->r.height = frame->crop.height; in gsc_m2m_g_selection()
476 return -EINVAL; in gsc_m2m_g_selection()
484 struct gsc_variant *variant = ctx->gsc_dev->variant; in gsc_m2m_s_selection()
488 if ((s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && in gsc_m2m_s_selection()
489 (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)) in gsc_m2m_s_selection()
490 return -EINVAL; in gsc_m2m_s_selection()
496 if (s->flags & V4L2_SEL_FLAG_LE && in gsc_m2m_s_selection()
497 !is_rectangle_enclosed(&sel.r, &s->r)) in gsc_m2m_s_selection()
498 return -ERANGE; in gsc_m2m_s_selection()
500 if (s->flags & V4L2_SEL_FLAG_GE && in gsc_m2m_s_selection()
501 !is_rectangle_enclosed(&s->r, &sel.r)) in gsc_m2m_s_selection()
502 return -ERANGE; in gsc_m2m_s_selection()
504 s->r = sel.r; in gsc_m2m_s_selection()
506 switch (s->target) { in gsc_m2m_s_selection()
510 frame = &ctx->s_frame; in gsc_m2m_s_selection()
516 frame = &ctx->d_frame; in gsc_m2m_s_selection()
520 return -EINVAL; in gsc_m2m_s_selection()
525 if (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { in gsc_m2m_s_selection()
527 sel.r.height, ctx->d_frame.crop.width, in gsc_m2m_s_selection()
528 ctx->d_frame.crop.height, in gsc_m2m_s_selection()
529 ctx->gsc_ctrls.rotate->val, ctx->out_path); in gsc_m2m_s_selection()
532 ctx->s_frame.crop.width, in gsc_m2m_s_selection()
533 ctx->s_frame.crop.height, sel.r.width, in gsc_m2m_s_selection()
534 sel.r.height, ctx->gsc_ctrls.rotate->val, in gsc_m2m_s_selection()
535 ctx->out_path); in gsc_m2m_s_selection()
539 pr_err("Out of scaler range"); in gsc_m2m_s_selection()
540 return -EINVAL; in gsc_m2m_s_selection()
544 frame->crop = sel.r; in gsc_m2m_s_selection()
578 src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; in queue_init()
579 src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; in queue_init()
580 src_vq->drv_priv = ctx; in queue_init()
581 src_vq->ops = &gsc_m2m_qops; in queue_init()
582 src_vq->mem_ops = &vb2_dma_contig_memops; in queue_init()
583 src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); in queue_init()
584 src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; in queue_init()
585 src_vq->lock = &ctx->gsc_dev->lock; in queue_init()
586 src_vq->dev = &ctx->gsc_dev->pdev->dev; in queue_init()
593 dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; in queue_init()
594 dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; in queue_init()
595 dst_vq->drv_priv = ctx; in queue_init()
596 dst_vq->ops = &gsc_m2m_qops; in queue_init()
597 dst_vq->mem_ops = &vb2_dma_contig_memops; in queue_init()
598 dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); in queue_init()
599 dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; in queue_init()
600 dst_vq->lock = &ctx->gsc_dev->lock; in queue_init()
601 dst_vq->dev = &ctx->gsc_dev->pdev->dev; in queue_init()
612 pr_debug("pid: %d, state: 0x%lx", task_pid_nr(current), gsc->state); in gsc_m2m_open()
614 if (mutex_lock_interruptible(&gsc->lock)) in gsc_m2m_open()
615 return -ERESTARTSYS; in gsc_m2m_open()
619 ret = -ENOMEM; in gsc_m2m_open()
623 v4l2_fh_init(&ctx->fh, gsc->m2m.vfd); in gsc_m2m_open()
629 ctx->fh.ctrl_handler = &ctx->ctrl_handler; in gsc_m2m_open()
630 file->private_data = &ctx->fh; in gsc_m2m_open()
631 v4l2_fh_add(&ctx->fh); in gsc_m2m_open()
633 ctx->gsc_dev = gsc; in gsc_m2m_open()
635 ctx->s_frame.fmt = get_format(0); in gsc_m2m_open()
636 ctx->d_frame.fmt = get_format(0); in gsc_m2m_open()
638 ctx->state = GSC_CTX_M2M; in gsc_m2m_open()
639 ctx->flags = 0; in gsc_m2m_open()
640 ctx->in_path = GSC_DMA; in gsc_m2m_open()
641 ctx->out_path = GSC_DMA; in gsc_m2m_open()
643 ctx->m2m_ctx = v4l2_m2m_ctx_init(gsc->m2m.m2m_dev, ctx, queue_init); in gsc_m2m_open()
644 if (IS_ERR(ctx->m2m_ctx)) { in gsc_m2m_open()
646 ret = PTR_ERR(ctx->m2m_ctx); in gsc_m2m_open()
650 if (gsc->m2m.refcnt++ == 0) in gsc_m2m_open()
651 set_bit(ST_M2M_OPEN, &gsc->state); in gsc_m2m_open()
655 mutex_unlock(&gsc->lock); in gsc_m2m_open()
660 v4l2_fh_del(&ctx->fh); in gsc_m2m_open()
662 v4l2_fh_exit(&ctx->fh); in gsc_m2m_open()
665 mutex_unlock(&gsc->lock); in gsc_m2m_open()
671 struct gsc_ctx *ctx = fh_to_ctx(file->private_data); in gsc_m2m_release()
672 struct gsc_dev *gsc = ctx->gsc_dev; in gsc_m2m_release()
675 task_pid_nr(current), gsc->state, gsc->m2m.refcnt); in gsc_m2m_release()
677 mutex_lock(&gsc->lock); in gsc_m2m_release()
679 v4l2_m2m_ctx_release(ctx->m2m_ctx); in gsc_m2m_release()
681 v4l2_fh_del(&ctx->fh); in gsc_m2m_release()
682 v4l2_fh_exit(&ctx->fh); in gsc_m2m_release()
684 if (--gsc->m2m.refcnt <= 0) in gsc_m2m_release()
685 clear_bit(ST_M2M_OPEN, &gsc->state); in gsc_m2m_release()
688 mutex_unlock(&gsc->lock); in gsc_m2m_release()
695 struct gsc_ctx *ctx = fh_to_ctx(file->private_data); in gsc_m2m_poll()
696 struct gsc_dev *gsc = ctx->gsc_dev; in gsc_m2m_poll()
699 if (mutex_lock_interruptible(&gsc->lock)) in gsc_m2m_poll()
702 ret = v4l2_m2m_poll(file, ctx->m2m_ctx, wait); in gsc_m2m_poll()
703 mutex_unlock(&gsc->lock); in gsc_m2m_poll()
710 struct gsc_ctx *ctx = fh_to_ctx(file->private_data); in gsc_m2m_mmap()
711 struct gsc_dev *gsc = ctx->gsc_dev; in gsc_m2m_mmap()
714 if (mutex_lock_interruptible(&gsc->lock)) in gsc_m2m_mmap()
715 return -ERESTARTSYS; in gsc_m2m_mmap()
717 ret = v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); in gsc_m2m_mmap()
718 mutex_unlock(&gsc->lock); in gsc_m2m_mmap()
743 return -ENODEV; in gsc_register_m2m_device()
745 pdev = gsc->pdev; in gsc_register_m2m_device()
747 gsc->vdev.fops = &gsc_m2m_fops; in gsc_register_m2m_device()
748 gsc->vdev.ioctl_ops = &gsc_m2m_ioctl_ops; in gsc_register_m2m_device()
749 gsc->vdev.release = video_device_release_empty; in gsc_register_m2m_device()
750 gsc->vdev.lock = &gsc->lock; in gsc_register_m2m_device()
751 gsc->vdev.vfl_dir = VFL_DIR_M2M; in gsc_register_m2m_device()
752 gsc->vdev.v4l2_dev = &gsc->v4l2_dev; in gsc_register_m2m_device()
753 gsc->vdev.device_caps = V4L2_CAP_STREAMING | in gsc_register_m2m_device()
755 snprintf(gsc->vdev.name, sizeof(gsc->vdev.name), "%s.%d:m2m", in gsc_register_m2m_device()
756 GSC_MODULE_NAME, gsc->id); in gsc_register_m2m_device()
758 video_set_drvdata(&gsc->vdev, gsc); in gsc_register_m2m_device()
760 gsc->m2m.vfd = &gsc->vdev; in gsc_register_m2m_device()
761 gsc->m2m.m2m_dev = v4l2_m2m_init(&gsc_m2m_ops); in gsc_register_m2m_device()
762 if (IS_ERR(gsc->m2m.m2m_dev)) { in gsc_register_m2m_device()
763 dev_err(&pdev->dev, "failed to initialize v4l2-m2m device\n"); in gsc_register_m2m_device()
764 return PTR_ERR(gsc->m2m.m2m_dev); in gsc_register_m2m_device()
767 ret = video_register_device(&gsc->vdev, VFL_TYPE_VIDEO, -1); in gsc_register_m2m_device()
769 dev_err(&pdev->dev, in gsc_register_m2m_device()
774 pr_debug("gsc m2m driver registered as /dev/video%d", gsc->vdev.num); in gsc_register_m2m_device()
778 v4l2_m2m_release(gsc->m2m.m2m_dev); in gsc_register_m2m_device()
786 v4l2_m2m_release(gsc->m2m.m2m_dev); in gsc_unregister_m2m_device()
787 video_unregister_device(&gsc->vdev); in gsc_unregister_m2m_device()