Lines Matching +full:sun8i +full:- +full:h3 +full:- +full:deinterlace
1 // SPDX-License-Identifier: GPL-2.0
3 * Allwinner sun8i deinterlacer with scaler driver
20 #include <media/v4l2-device.h>
21 #include <media/v4l2-ioctl.h>
22 #include <media/v4l2-mem2mem.h>
24 #include "sun8i-di.h"
35 return readl(dev->base + reg); in deinterlace_read()
41 writel(value, dev->base + reg); in deinterlace_write()
47 writel(readl(dev->base + reg) | bits, dev->base + reg); in deinterlace_set_bits()
53 u32 val = readl(dev->base + reg); in deinterlace_clr_set_bits()
58 writel(val, dev->base + reg); in deinterlace_clr_set_bits()
64 struct deinterlace_dev *dev = ctx->dev; in deinterlace_device_run()
71 src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); in deinterlace_device_run()
72 dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); in deinterlace_device_run()
79 if (ctx->field) { in deinterlace_device_run()
81 ctx->flag1_buf_dma); in deinterlace_device_run()
83 ctx->flag2_buf_dma); in deinterlace_device_run()
86 ctx->flag2_buf_dma); in deinterlace_device_run()
88 ctx->flag1_buf_dma); in deinterlace_device_run()
92 width = ctx->src_fmt.width; in deinterlace_device_run()
93 height = ctx->src_fmt.height; in deinterlace_device_run()
94 stride = ctx->src_fmt.bytesperline; in deinterlace_device_run()
97 addr = vb2_dma_contig_plane_dma_addr(&src->vb2_buf, 0); in deinterlace_device_run()
112 switch (ctx->src_fmt.pixelformat) { in deinterlace_device_run()
122 if (ctx->prev) in deinterlace_device_run()
123 addr = vb2_dma_contig_plane_dma_addr(&ctx->prev->vb2_buf, 0); in deinterlace_device_run()
129 switch (ctx->src_fmt.pixelformat) { in deinterlace_device_run()
139 width = ctx->dst_fmt.width; in deinterlace_device_run()
140 height = ctx->dst_fmt.height; in deinterlace_device_run()
141 stride = ctx->dst_fmt.bytesperline; in deinterlace_device_run()
152 addr = vb2_dma_contig_plane_dma_addr(&dst->vb2_buf, 0); in deinterlace_device_run()
157 hstep = (ctx->src_fmt.width << 16) / ctx->dst_fmt.width; in deinterlace_device_run()
158 vstep = (ctx->src_fmt.height << 16) / ctx->dst_fmt.height; in deinterlace_device_run()
167 readl_poll_timeout(dev->base + DEINTERLACE_STATUS, val, in deinterlace_device_run()
186 DEINTERLACE_FIELD_CTRL_FIELD_CNT(ctx->field)); in deinterlace_device_run()
205 return v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) >= 1 && in deinterlace_job_ready()
206 v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx) >= 2; in deinterlace_job_ready()
214 ctx->aborting = 1; in deinterlace_job_abort()
225 ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev); in deinterlace_irq()
227 v4l2_err(&dev->v4l2_dev, in deinterlace_irq()
249 dst = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); in deinterlace_irq()
252 if (ctx->field != ctx->first_field || ctx->aborting) { in deinterlace_irq()
253 ctx->field = ctx->first_field; in deinterlace_irq()
255 src = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); in deinterlace_irq()
256 if (ctx->prev) in deinterlace_irq()
257 v4l2_m2m_buf_done(ctx->prev, state); in deinterlace_irq()
258 ctx->prev = src; in deinterlace_irq()
260 v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx); in deinterlace_irq()
262 ctx->field = !ctx->first_field; in deinterlace_irq()
312 return container_of(file->private_data, struct deinterlace_ctx, fh); in deinterlace_file2ctx()
328 unsigned int height = pix_fmt->height; in deinterlace_prepare_format()
329 unsigned int width = pix_fmt->width; in deinterlace_prepare_format()
344 pix_fmt->width = width; in deinterlace_prepare_format()
345 pix_fmt->height = height; in deinterlace_prepare_format()
346 pix_fmt->bytesperline = bytesperline; in deinterlace_prepare_format()
347 pix_fmt->sizeimage = sizeimage; in deinterlace_prepare_format()
353 strscpy(cap->driver, DEINTERLACE_NAME, sizeof(cap->driver)); in deinterlace_querycap()
354 strscpy(cap->card, DEINTERLACE_NAME, sizeof(cap->card)); in deinterlace_querycap()
355 snprintf(cap->bus_info, sizeof(cap->bus_info), in deinterlace_querycap()
364 if (f->index < ARRAY_SIZE(deinterlace_formats)) { in deinterlace_enum_fmt()
365 f->pixelformat = deinterlace_formats[f->index]; in deinterlace_enum_fmt()
370 return -EINVAL; in deinterlace_enum_fmt()
376 if (fsize->index != 0) in deinterlace_enum_framesizes()
377 return -EINVAL; in deinterlace_enum_framesizes()
379 if (!deinterlace_check_format(fsize->pixel_format)) in deinterlace_enum_framesizes()
380 return -EINVAL; in deinterlace_enum_framesizes()
382 fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; in deinterlace_enum_framesizes()
383 fsize->stepwise.min_width = DEINTERLACE_MIN_WIDTH; in deinterlace_enum_framesizes()
384 fsize->stepwise.min_height = DEINTERLACE_MIN_HEIGHT; in deinterlace_enum_framesizes()
385 fsize->stepwise.max_width = DEINTERLACE_MAX_WIDTH; in deinterlace_enum_framesizes()
386 fsize->stepwise.max_height = DEINTERLACE_MAX_HEIGHT; in deinterlace_enum_framesizes()
387 fsize->stepwise.step_width = 2; in deinterlace_enum_framesizes()
388 fsize->stepwise.step_height = 1; in deinterlace_enum_framesizes()
398 f->fmt.pix = ctx->dst_fmt; in deinterlace_g_fmt_vid_cap()
408 f->fmt.pix = ctx->src_fmt; in deinterlace_g_fmt_vid_out()
416 if (!deinterlace_check_format(f->fmt.pix.pixelformat)) in deinterlace_try_fmt_vid_cap()
417 f->fmt.pix.pixelformat = deinterlace_formats[0]; in deinterlace_try_fmt_vid_cap()
419 if (f->fmt.pix.field != V4L2_FIELD_NONE) in deinterlace_try_fmt_vid_cap()
420 f->fmt.pix.field = V4L2_FIELD_NONE; in deinterlace_try_fmt_vid_cap()
422 deinterlace_prepare_format(&f->fmt.pix); in deinterlace_try_fmt_vid_cap()
430 if (!deinterlace_check_format(f->fmt.pix.pixelformat)) in deinterlace_try_fmt_vid_out()
431 f->fmt.pix.pixelformat = deinterlace_formats[0]; in deinterlace_try_fmt_vid_out()
433 if (f->fmt.pix.field != V4L2_FIELD_INTERLACED_TB && in deinterlace_try_fmt_vid_out()
434 f->fmt.pix.field != V4L2_FIELD_INTERLACED_BT && in deinterlace_try_fmt_vid_out()
435 f->fmt.pix.field != V4L2_FIELD_INTERLACED) in deinterlace_try_fmt_vid_out()
436 f->fmt.pix.field = V4L2_FIELD_INTERLACED; in deinterlace_try_fmt_vid_out()
438 deinterlace_prepare_format(&f->fmt.pix); in deinterlace_try_fmt_vid_out()
454 vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); in deinterlace_s_fmt_vid_cap()
456 return -EBUSY; in deinterlace_s_fmt_vid_cap()
458 ctx->dst_fmt = f->fmt.pix; in deinterlace_s_fmt_vid_cap()
474 vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); in deinterlace_s_fmt_vid_out()
476 return -EBUSY; in deinterlace_s_fmt_vid_out()
478 ctx->src_fmt = f->fmt.pix; in deinterlace_s_fmt_vid_out()
481 ctx->dst_fmt.colorspace = f->fmt.pix.colorspace; in deinterlace_s_fmt_vid_out()
482 ctx->dst_fmt.xfer_func = f->fmt.pix.xfer_func; in deinterlace_s_fmt_vid_out()
483 ctx->dst_fmt.ycbcr_enc = f->fmt.pix.ycbcr_enc; in deinterlace_s_fmt_vid_out()
484 ctx->dst_fmt.quantization = f->fmt.pix.quantization; in deinterlace_s_fmt_vid_out()
523 if (V4L2_TYPE_IS_OUTPUT(vq->type)) in deinterlace_queue_setup()
524 pix_fmt = &ctx->src_fmt; in deinterlace_queue_setup()
526 pix_fmt = &ctx->dst_fmt; in deinterlace_queue_setup()
529 if (sizes[0] < pix_fmt->sizeimage) in deinterlace_queue_setup()
530 return -EINVAL; in deinterlace_queue_setup()
532 sizes[0] = pix_fmt->sizeimage; in deinterlace_queue_setup()
541 struct vb2_queue *vq = vb->vb2_queue; in deinterlace_buf_prepare()
545 if (V4L2_TYPE_IS_OUTPUT(vq->type)) in deinterlace_buf_prepare()
546 pix_fmt = &ctx->src_fmt; in deinterlace_buf_prepare()
548 pix_fmt = &ctx->dst_fmt; in deinterlace_buf_prepare()
550 if (vb2_plane_size(vb, 0) < pix_fmt->sizeimage) in deinterlace_buf_prepare()
551 return -EINVAL; in deinterlace_buf_prepare()
553 vb2_set_plane_payload(vb, 0, pix_fmt->sizeimage); in deinterlace_buf_prepare()
561 struct deinterlace_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); in deinterlace_buf_queue()
563 v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); in deinterlace_buf_queue()
572 if (V4L2_TYPE_IS_OUTPUT(vq->type)) in deinterlace_queue_cleanup()
573 vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); in deinterlace_queue_cleanup()
575 vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); in deinterlace_queue_cleanup()
581 if (V4L2_TYPE_IS_OUTPUT(vq->type) && ctx->prev) in deinterlace_queue_cleanup()
582 v4l2_m2m_buf_done(ctx->prev, state); in deinterlace_queue_cleanup()
588 struct device *dev = ctx->dev->dev; in deinterlace_start_streaming()
591 if (V4L2_TYPE_IS_OUTPUT(vq->type)) { in deinterlace_start_streaming()
599 ctx->first_field = in deinterlace_start_streaming()
600 ctx->src_fmt.field == V4L2_FIELD_INTERLACED_BT; in deinterlace_start_streaming()
601 ctx->field = ctx->first_field; in deinterlace_start_streaming()
603 ctx->prev = NULL; in deinterlace_start_streaming()
604 ctx->aborting = 0; in deinterlace_start_streaming()
606 ctx->flag1_buf = dma_alloc_coherent(dev, FLAG_SIZE, in deinterlace_start_streaming()
607 &ctx->flag1_buf_dma, in deinterlace_start_streaming()
609 if (!ctx->flag1_buf) { in deinterlace_start_streaming()
610 ret = -ENOMEM; in deinterlace_start_streaming()
615 ctx->flag2_buf = dma_alloc_coherent(dev, FLAG_SIZE, in deinterlace_start_streaming()
616 &ctx->flag2_buf_dma, in deinterlace_start_streaming()
618 if (!ctx->flag2_buf) { in deinterlace_start_streaming()
619 ret = -ENOMEM; in deinterlace_start_streaming()
628 dma_free_coherent(dev, FLAG_SIZE, ctx->flag1_buf, in deinterlace_start_streaming()
629 ctx->flag1_buf_dma); in deinterlace_start_streaming()
642 if (V4L2_TYPE_IS_OUTPUT(vq->type)) { in deinterlace_stop_streaming()
643 struct device *dev = ctx->dev->dev; in deinterlace_stop_streaming()
645 dma_free_coherent(dev, FLAG_SIZE, ctx->flag1_buf, in deinterlace_stop_streaming()
646 ctx->flag1_buf_dma); in deinterlace_stop_streaming()
647 dma_free_coherent(dev, FLAG_SIZE, ctx->flag2_buf, in deinterlace_stop_streaming()
648 ctx->flag2_buf_dma); in deinterlace_stop_streaming()
672 src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; in deinterlace_queue_init()
673 src_vq->io_modes = VB2_MMAP | VB2_DMABUF; in deinterlace_queue_init()
674 src_vq->drv_priv = ctx; in deinterlace_queue_init()
675 src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); in deinterlace_queue_init()
676 src_vq->min_queued_buffers = 1; in deinterlace_queue_init()
677 src_vq->ops = &deinterlace_qops; in deinterlace_queue_init()
678 src_vq->mem_ops = &vb2_dma_contig_memops; in deinterlace_queue_init()
679 src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; in deinterlace_queue_init()
680 src_vq->lock = &ctx->dev->dev_mutex; in deinterlace_queue_init()
681 src_vq->dev = ctx->dev->dev; in deinterlace_queue_init()
687 dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; in deinterlace_queue_init()
688 dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; in deinterlace_queue_init()
689 dst_vq->drv_priv = ctx; in deinterlace_queue_init()
690 dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); in deinterlace_queue_init()
691 dst_vq->min_queued_buffers = 2; in deinterlace_queue_init()
692 dst_vq->ops = &deinterlace_qops; in deinterlace_queue_init()
693 dst_vq->mem_ops = &vb2_dma_contig_memops; in deinterlace_queue_init()
694 dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; in deinterlace_queue_init()
695 dst_vq->lock = &ctx->dev->dev_mutex; in deinterlace_queue_init()
696 dst_vq->dev = ctx->dev->dev; in deinterlace_queue_init()
711 if (mutex_lock_interruptible(&dev->dev_mutex)) in deinterlace_open()
712 return -ERESTARTSYS; in deinterlace_open()
716 mutex_unlock(&dev->dev_mutex); in deinterlace_open()
717 return -ENOMEM; in deinterlace_open()
721 ctx->src_fmt.pixelformat = deinterlace_formats[0]; in deinterlace_open()
722 ctx->src_fmt.field = V4L2_FIELD_INTERLACED; in deinterlace_open()
723 ctx->src_fmt.width = 640; in deinterlace_open()
724 ctx->src_fmt.height = 480; in deinterlace_open()
725 deinterlace_prepare_format(&ctx->src_fmt); in deinterlace_open()
728 ctx->dst_fmt.pixelformat = deinterlace_formats[0]; in deinterlace_open()
729 ctx->dst_fmt.field = V4L2_FIELD_NONE; in deinterlace_open()
730 ctx->dst_fmt.width = 640; in deinterlace_open()
731 ctx->dst_fmt.height = 480; in deinterlace_open()
732 deinterlace_prepare_format(&ctx->dst_fmt); in deinterlace_open()
734 v4l2_fh_init(&ctx->fh, video_devdata(file)); in deinterlace_open()
735 file->private_data = &ctx->fh; in deinterlace_open()
736 ctx->dev = dev; in deinterlace_open()
738 ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, in deinterlace_open()
740 if (IS_ERR(ctx->fh.m2m_ctx)) { in deinterlace_open()
741 ret = PTR_ERR(ctx->fh.m2m_ctx); in deinterlace_open()
745 v4l2_fh_add(&ctx->fh); in deinterlace_open()
747 mutex_unlock(&dev->dev_mutex); in deinterlace_open()
753 mutex_unlock(&dev->dev_mutex); in deinterlace_open()
761 struct deinterlace_ctx *ctx = container_of(file->private_data, in deinterlace_release()
764 mutex_lock(&dev->dev_mutex); in deinterlace_release()
766 v4l2_fh_del(&ctx->fh); in deinterlace_release()
767 v4l2_fh_exit(&ctx->fh); in deinterlace_release()
768 v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); in deinterlace_release()
772 mutex_unlock(&dev->dev_mutex); in deinterlace_release()
791 .minor = -1,
808 dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); in deinterlace_probe()
810 return -ENOMEM; in deinterlace_probe()
812 dev->vfd = deinterlace_video_device; in deinterlace_probe()
813 dev->dev = &pdev->dev; in deinterlace_probe()
819 ret = devm_request_irq(dev->dev, irq, deinterlace_irq, in deinterlace_probe()
820 0, dev_name(dev->dev), dev); in deinterlace_probe()
822 dev_err(dev->dev, "Failed to request IRQ\n"); in deinterlace_probe()
827 dev->base = devm_platform_ioremap_resource(pdev, 0); in deinterlace_probe()
828 if (IS_ERR(dev->base)) in deinterlace_probe()
829 return PTR_ERR(dev->base); in deinterlace_probe()
831 dev->bus_clk = devm_clk_get(dev->dev, "bus"); in deinterlace_probe()
832 if (IS_ERR(dev->bus_clk)) { in deinterlace_probe()
833 dev_err(dev->dev, "Failed to get bus clock\n"); in deinterlace_probe()
835 return PTR_ERR(dev->bus_clk); in deinterlace_probe()
838 dev->mod_clk = devm_clk_get(dev->dev, "mod"); in deinterlace_probe()
839 if (IS_ERR(dev->mod_clk)) { in deinterlace_probe()
840 dev_err(dev->dev, "Failed to get mod clock\n"); in deinterlace_probe()
842 return PTR_ERR(dev->mod_clk); in deinterlace_probe()
845 dev->ram_clk = devm_clk_get(dev->dev, "ram"); in deinterlace_probe()
846 if (IS_ERR(dev->ram_clk)) { in deinterlace_probe()
847 dev_err(dev->dev, "Failed to get ram clock\n"); in deinterlace_probe()
849 return PTR_ERR(dev->ram_clk); in deinterlace_probe()
852 dev->rstc = devm_reset_control_get(dev->dev, NULL); in deinterlace_probe()
853 if (IS_ERR(dev->rstc)) { in deinterlace_probe()
854 dev_err(dev->dev, "Failed to get reset control\n"); in deinterlace_probe()
856 return PTR_ERR(dev->rstc); in deinterlace_probe()
859 mutex_init(&dev->dev_mutex); in deinterlace_probe()
861 ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); in deinterlace_probe()
863 dev_err(dev->dev, "Failed to register V4L2 device\n"); in deinterlace_probe()
868 vfd = &dev->vfd; in deinterlace_probe()
869 vfd->lock = &dev->dev_mutex; in deinterlace_probe()
870 vfd->v4l2_dev = &dev->v4l2_dev; in deinterlace_probe()
872 snprintf(vfd->name, sizeof(vfd->name), "%s", in deinterlace_probe()
878 v4l2_err(&dev->v4l2_dev, "Failed to register video device\n"); in deinterlace_probe()
883 v4l2_info(&dev->v4l2_dev, in deinterlace_probe()
884 "Device registered as /dev/video%d\n", vfd->num); in deinterlace_probe()
886 dev->m2m_dev = v4l2_m2m_init(&deinterlace_m2m_ops); in deinterlace_probe()
887 if (IS_ERR(dev->m2m_dev)) { in deinterlace_probe()
888 v4l2_err(&dev->v4l2_dev, in deinterlace_probe()
890 ret = PTR_ERR(dev->m2m_dev); in deinterlace_probe()
897 pm_runtime_enable(dev->dev); in deinterlace_probe()
902 video_unregister_device(&dev->vfd); in deinterlace_probe()
904 v4l2_device_unregister(&dev->v4l2_dev); in deinterlace_probe()
913 v4l2_m2m_release(dev->m2m_dev); in deinterlace_remove()
914 video_unregister_device(&dev->vfd); in deinterlace_remove()
915 v4l2_device_unregister(&dev->v4l2_dev); in deinterlace_remove()
917 pm_runtime_force_suspend(&pdev->dev); in deinterlace_remove()
925 ret = clk_set_rate_exclusive(dev->mod_clk, 300000000); in deinterlace_runtime_resume()
927 dev_err(dev->dev, "Failed to set exclusive mod clock rate\n"); in deinterlace_runtime_resume()
932 ret = reset_control_deassert(dev->rstc); in deinterlace_runtime_resume()
934 dev_err(dev->dev, "Failed to apply reset\n"); in deinterlace_runtime_resume()
939 ret = clk_prepare_enable(dev->bus_clk); in deinterlace_runtime_resume()
941 dev_err(dev->dev, "Failed to enable bus clock\n"); in deinterlace_runtime_resume()
946 ret = clk_prepare_enable(dev->mod_clk); in deinterlace_runtime_resume()
948 dev_err(dev->dev, "Failed to enable mod clock\n"); in deinterlace_runtime_resume()
953 ret = clk_prepare_enable(dev->ram_clk); in deinterlace_runtime_resume()
955 dev_err(dev->dev, "Failed to enable ram clock\n"); in deinterlace_runtime_resume()
965 clk_disable_unprepare(dev->mod_clk); in deinterlace_runtime_resume()
967 clk_disable_unprepare(dev->bus_clk); in deinterlace_runtime_resume()
969 reset_control_assert(dev->rstc); in deinterlace_runtime_resume()
971 clk_rate_exclusive_put(dev->mod_clk); in deinterlace_runtime_resume()
980 clk_disable_unprepare(dev->ram_clk); in deinterlace_runtime_suspend()
981 clk_disable_unprepare(dev->mod_clk); in deinterlace_runtime_suspend()
982 clk_disable_unprepare(dev->bus_clk); in deinterlace_runtime_suspend()
984 reset_control_assert(dev->rstc); in deinterlace_runtime_suspend()
986 clk_rate_exclusive_put(dev->mod_clk); in deinterlace_runtime_suspend()
992 { .compatible = "allwinner,sun8i-h3-deinterlace" },
1015 MODULE_DESCRIPTION("Allwinner Deinterlace driver");