Lines Matching +full:pix +full:- +full:limits
1 // SPDX-License-Identifier: GPL-2.0-only
5 * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
8 * Author: Jai Luthra <j-luthra@ti.com>
17 #include <media/mipi-csi2.h>
18 #include <media/v4l2-device.h>
19 #include <media/v4l2-ioctl.h>
20 #include <media/v4l2-mc.h>
21 #include <media/videobuf2-dma-contig.h>
23 #define TI_CSI2RX_MODULE_NAME "j721e-csi2rx"
44 * There are no hard limits on the width or height. The DMA engine can handle
87 /* Buffer to drain stale data from PSI-L endpoint */
245 struct v4l2_pix_format *pix = &v4l2_fmt->fmt.pix; in ti_csi2rx_fill_fmt() local
248 pixels_in_word = PSIL_WORD_SIZE_BYTES * 8 / csi_fmt->bpp; in ti_csi2rx_fill_fmt()
251 pix->width = clamp_t(unsigned int, pix->width, in ti_csi2rx_fill_fmt()
253 MAX_WIDTH_BYTES * 8 / csi_fmt->bpp); in ti_csi2rx_fill_fmt()
254 pix->height = clamp_t(unsigned int, pix->height, 1, MAX_HEIGHT_LINES); in ti_csi2rx_fill_fmt()
256 /* Width should be a multiple of transfer word-size */ in ti_csi2rx_fill_fmt()
257 pix->width = rounddown(pix->width, pixels_in_word); in ti_csi2rx_fill_fmt()
259 v4l2_fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; in ti_csi2rx_fill_fmt()
260 pix->pixelformat = csi_fmt->fourcc; in ti_csi2rx_fill_fmt()
261 pix->bytesperline = pix->width * (csi_fmt->bpp / 8); in ti_csi2rx_fill_fmt()
262 pix->sizeimage = pix->bytesperline * pix->height; in ti_csi2rx_fill_fmt()
268 strscpy(cap->driver, TI_CSI2RX_MODULE_NAME, sizeof(cap->driver)); in ti_csi2rx_querycap()
269 strscpy(cap->card, TI_CSI2RX_MODULE_NAME, sizeof(cap->card)); in ti_csi2rx_querycap()
279 if (f->mbus_code) { in ti_csi2rx_enum_fmt_vid_cap()
280 /* 1-to-1 mapping between bus formats and pixel formats */ in ti_csi2rx_enum_fmt_vid_cap()
281 if (f->index > 0) in ti_csi2rx_enum_fmt_vid_cap()
282 return -EINVAL; in ti_csi2rx_enum_fmt_vid_cap()
284 fmt = find_format_by_code(f->mbus_code); in ti_csi2rx_enum_fmt_vid_cap()
286 if (f->index >= ARRAY_SIZE(ti_csi2rx_formats)) in ti_csi2rx_enum_fmt_vid_cap()
287 return -EINVAL; in ti_csi2rx_enum_fmt_vid_cap()
289 fmt = &ti_csi2rx_formats[f->index]; in ti_csi2rx_enum_fmt_vid_cap()
293 return -EINVAL; in ti_csi2rx_enum_fmt_vid_cap()
295 f->pixelformat = fmt->fourcc; in ti_csi2rx_enum_fmt_vid_cap()
296 memset(f->reserved, 0, sizeof(f->reserved)); in ti_csi2rx_enum_fmt_vid_cap()
297 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; in ti_csi2rx_enum_fmt_vid_cap()
307 *f = csi->v_fmt; in ti_csi2rx_g_fmt_vid_cap()
321 fmt = find_format_by_fourcc(f->fmt.pix.pixelformat); in ti_csi2rx_try_fmt_vid_cap()
326 f->fmt.pix.field = V4L2_FIELD_NONE; in ti_csi2rx_try_fmt_vid_cap()
337 struct vb2_queue *q = &csi->vidq; in ti_csi2rx_s_fmt_vid_cap()
341 return -EBUSY; in ti_csi2rx_s_fmt_vid_cap()
347 csi->v_fmt = *f; in ti_csi2rx_s_fmt_vid_cap()
358 fmt = find_format_by_fourcc(fsize->pixel_format); in ti_csi2rx_enum_framesizes()
359 if (!fmt || fsize->index != 0) in ti_csi2rx_enum_framesizes()
360 return -EINVAL; in ti_csi2rx_enum_framesizes()
363 * Number of pixels in one PSI-L word. The transfer happens in multiples in ti_csi2rx_enum_framesizes()
364 * of PSI-L word sizes. in ti_csi2rx_enum_framesizes()
366 pixels_in_word = PSIL_WORD_SIZE_BYTES * 8 / fmt->bpp; in ti_csi2rx_enum_framesizes()
368 fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; in ti_csi2rx_enum_framesizes()
369 fsize->stepwise.min_width = pixels_in_word; in ti_csi2rx_enum_framesizes()
370 fsize->stepwise.max_width = rounddown(MAX_WIDTH_BYTES * 8 / fmt->bpp, in ti_csi2rx_enum_framesizes()
372 fsize->stepwise.step_width = pixels_in_word; in ti_csi2rx_enum_framesizes()
373 fsize->stepwise.min_height = 1; in ti_csi2rx_enum_framesizes()
374 fsize->stepwise.max_height = MAX_HEIGHT_LINES; in ti_csi2rx_enum_framesizes()
375 fsize->stepwise.step_height = 1; in ti_csi2rx_enum_framesizes()
412 struct ti_csi2rx_dev *csi = dev_get_drvdata(notifier->v4l2_dev->dev); in csi_async_notifier_bound()
414 csi->source = subdev; in csi_async_notifier_bound()
421 struct ti_csi2rx_dev *csi = dev_get_drvdata(notifier->v4l2_dev->dev); in csi_async_notifier_complete()
422 struct video_device *vdev = &csi->vdev; in csi_async_notifier_complete()
425 ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); in csi_async_notifier_complete()
429 ret = v4l2_create_fwnode_links_to_pad(csi->source, &csi->pad, in csi_async_notifier_complete()
437 ret = v4l2_device_register_subdev_nodes(&csi->v4l2_dev); in csi_async_notifier_complete()
456 node = of_get_child_by_name(csi->dev->of_node, "csi-bridge"); in ti_csi2rx_notifier_register()
458 return -EINVAL; in ti_csi2rx_notifier_register()
463 return -EINVAL; in ti_csi2rx_notifier_register()
466 v4l2_async_nf_init(&csi->notifier, &csi->v4l2_dev); in ti_csi2rx_notifier_register()
467 csi->notifier.ops = &csi_async_notifier_ops; in ti_csi2rx_notifier_register()
469 asc = v4l2_async_nf_add_fwnode(&csi->notifier, fwnode, in ti_csi2rx_notifier_register()
473 v4l2_async_nf_cleanup(&csi->notifier); in ti_csi2rx_notifier_register()
477 ret = v4l2_async_nf_register(&csi->notifier); in ti_csi2rx_notifier_register()
479 v4l2_async_nf_cleanup(&csi->notifier); in ti_csi2rx_notifier_register()
491 fmt = find_format_by_fourcc(csi->v_fmt.fmt.pix.pixelformat); in ti_csi2rx_setup_shim()
493 /* De-assert the pixel interface reset. */ in ti_csi2rx_setup_shim()
495 writel(reg, csi->shim + SHIM_CNTL); in ti_csi2rx_setup_shim()
498 reg |= FIELD_PREP(SHIM_DMACNTX_FMT, fmt->csi_dt); in ti_csi2rx_setup_shim()
501 * The hardware assumes incoming YUV422 8-bit data on MIPI CSI2 bus in ti_csi2rx_setup_shim()
502 * follows the spec and is packed in the order U0 -> Y0 -> V0 -> Y1 -> in ti_csi2rx_setup_shim()
508 * Byte3 <----------- Byte0 in ti_csi2rx_setup_shim()
518 switch (fmt->fourcc) { in ti_csi2rx_setup_shim()
531 reg |= FIELD_PREP(SHIM_DMACNTX_SIZE, fmt->size); in ti_csi2rx_setup_shim()
533 writel(reg, csi->shim + SHIM_DMACNTX); in ti_csi2rx_setup_shim()
537 writel(reg, csi->shim + SHIM_PSI_CFG0); in ti_csi2rx_setup_shim()
548 * Drain the stale data left at the PSI-L endpoint.
551 * streaming. In multi-stream scenarios this can happen when one stream is
552 * stopped but other is still streaming, and thus module-level pixel reset is
567 desc = dmaengine_prep_slave_single(csi->dma.chan, csi->dma.drain.paddr, in ti_csi2rx_drain_dma()
568 csi->dma.drain.len, DMA_DEV_TO_MEM, in ti_csi2rx_drain_dma()
571 ret = -EIO; in ti_csi2rx_drain_dma()
575 desc->callback = ti_csi2rx_drain_callback; in ti_csi2rx_drain_dma()
576 desc->callback_param = &drain_complete; in ti_csi2rx_drain_dma()
583 dma_async_issue_pending(csi->dma.chan); in ti_csi2rx_drain_dma()
587 dmaengine_terminate_sync(csi->dma.chan); in ti_csi2rx_drain_dma()
588 dev_dbg(csi->dev, "DMA transfer timed out for drain buffer\n"); in ti_csi2rx_drain_dma()
589 ret = -ETIMEDOUT; in ti_csi2rx_drain_dma()
599 struct ti_csi2rx_dev *csi = buf->csi; in ti_csi2rx_dma_callback()
600 struct ti_csi2rx_dma *dma = &csi->dma; in ti_csi2rx_dma_callback()
607 buf->vb.vb2_buf.timestamp = ktime_get_ns(); in ti_csi2rx_dma_callback()
608 buf->vb.sequence = csi->sequence++; in ti_csi2rx_dma_callback()
610 spin_lock_irqsave(&dma->lock, flags); in ti_csi2rx_dma_callback()
612 WARN_ON(!list_is_first(&buf->list, &dma->submitted)); in ti_csi2rx_dma_callback()
613 vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE); in ti_csi2rx_dma_callback()
614 list_del(&buf->list); in ti_csi2rx_dma_callback()
617 while (!list_empty(&dma->queue)) { in ti_csi2rx_dma_callback()
618 buf = list_entry(dma->queue.next, struct ti_csi2rx_buffer, list); in ti_csi2rx_dma_callback()
621 dev_err(csi->dev, "Failed to queue the next buffer for DMA\n"); in ti_csi2rx_dma_callback()
622 vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); in ti_csi2rx_dma_callback()
624 list_move_tail(&buf->list, &dma->submitted); in ti_csi2rx_dma_callback()
628 if (list_empty(&dma->submitted)) in ti_csi2rx_dma_callback()
629 dma->state = TI_CSI2RX_DMA_IDLE; in ti_csi2rx_dma_callback()
631 spin_unlock_irqrestore(&dma->lock, flags); in ti_csi2rx_dma_callback()
639 size_t len = csi->v_fmt.fmt.pix.sizeimage; in ti_csi2rx_start_dma()
643 addr = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0); in ti_csi2rx_start_dma()
644 desc = dmaengine_prep_slave_single(csi->dma.chan, addr, len, in ti_csi2rx_start_dma()
648 return -EIO; in ti_csi2rx_start_dma()
650 desc->callback = ti_csi2rx_dma_callback; in ti_csi2rx_start_dma()
651 desc->callback_param = buf; in ti_csi2rx_start_dma()
658 dma_async_issue_pending(csi->dma.chan); in ti_csi2rx_start_dma()
665 struct ti_csi2rx_dma *dma = &csi->dma; in ti_csi2rx_stop_dma()
670 spin_lock_irqsave(&dma->lock, flags); in ti_csi2rx_stop_dma()
671 state = csi->dma.state; in ti_csi2rx_stop_dma()
672 dma->state = TI_CSI2RX_DMA_STOPPED; in ti_csi2rx_stop_dma()
673 spin_unlock_irqrestore(&dma->lock, flags); in ti_csi2rx_stop_dma()
679 * is stopped, as the module-level pixel reset cannot be in ti_csi2rx_stop_dma()
683 if (ret && ret != -ETIMEDOUT) in ti_csi2rx_stop_dma()
684 dev_warn(csi->dev, in ti_csi2rx_stop_dma()
688 ret = dmaengine_terminate_sync(csi->dma.chan); in ti_csi2rx_stop_dma()
690 dev_err(csi->dev, "Failed to stop DMA: %d\n", ret); in ti_csi2rx_stop_dma()
696 struct ti_csi2rx_dma *dma = &csi->dma; in ti_csi2rx_cleanup_buffers()
700 spin_lock_irqsave(&dma->lock, flags); in ti_csi2rx_cleanup_buffers()
701 list_for_each_entry_safe(buf, tmp, &csi->dma.queue, list) { in ti_csi2rx_cleanup_buffers()
702 list_del(&buf->list); in ti_csi2rx_cleanup_buffers()
703 vb2_buffer_done(&buf->vb.vb2_buf, state); in ti_csi2rx_cleanup_buffers()
705 list_for_each_entry_safe(buf, tmp, &csi->dma.submitted, list) { in ti_csi2rx_cleanup_buffers()
706 list_del(&buf->list); in ti_csi2rx_cleanup_buffers()
707 vb2_buffer_done(&buf->vb.vb2_buf, state); in ti_csi2rx_cleanup_buffers()
709 spin_unlock_irqrestore(&dma->lock, flags); in ti_csi2rx_cleanup_buffers()
717 unsigned int size = csi->v_fmt.fmt.pix.sizeimage; in ti_csi2rx_queue_setup()
721 return -EINVAL; in ti_csi2rx_queue_setup()
733 struct ti_csi2rx_dev *csi = vb2_get_drv_priv(vb->vb2_queue); in ti_csi2rx_buffer_prepare()
734 unsigned long size = csi->v_fmt.fmt.pix.sizeimage; in ti_csi2rx_buffer_prepare()
737 dev_err(csi->dev, "Data will not fit into plane\n"); in ti_csi2rx_buffer_prepare()
738 return -EINVAL; in ti_csi2rx_buffer_prepare()
747 struct ti_csi2rx_dev *csi = vb2_get_drv_priv(vb->vb2_queue); in ti_csi2rx_buffer_queue()
749 struct ti_csi2rx_dma *dma = &csi->dma; in ti_csi2rx_buffer_queue()
755 buf->csi = csi; in ti_csi2rx_buffer_queue()
757 spin_lock_irqsave(&dma->lock, flags); in ti_csi2rx_buffer_queue()
762 if (dma->state == TI_CSI2RX_DMA_IDLE) { in ti_csi2rx_buffer_queue()
770 dma->state = TI_CSI2RX_DMA_ACTIVE; in ti_csi2rx_buffer_queue()
772 list_add_tail(&buf->list, &dma->queue); in ti_csi2rx_buffer_queue()
774 spin_unlock_irqrestore(&dma->lock, flags); in ti_csi2rx_buffer_queue()
785 if (ret && ret != -ETIMEDOUT) in ti_csi2rx_buffer_queue()
786 dev_warn(csi->dev, in ti_csi2rx_buffer_queue()
789 spin_lock_irqsave(&dma->lock, flags); in ti_csi2rx_buffer_queue()
792 vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); in ti_csi2rx_buffer_queue()
793 dma->state = TI_CSI2RX_DMA_IDLE; in ti_csi2rx_buffer_queue()
794 spin_unlock_irqrestore(&dma->lock, flags); in ti_csi2rx_buffer_queue()
795 dev_err(csi->dev, "Failed to start DMA: %d\n", ret); in ti_csi2rx_buffer_queue()
797 list_add_tail(&buf->list, &dma->submitted); in ti_csi2rx_buffer_queue()
798 spin_unlock_irqrestore(&dma->lock, flags); in ti_csi2rx_buffer_queue()
806 struct ti_csi2rx_dma *dma = &csi->dma; in ti_csi2rx_start_streaming()
811 spin_lock_irqsave(&dma->lock, flags); in ti_csi2rx_start_streaming()
812 if (list_empty(&dma->queue)) in ti_csi2rx_start_streaming()
813 ret = -EIO; in ti_csi2rx_start_streaming()
814 spin_unlock_irqrestore(&dma->lock, flags); in ti_csi2rx_start_streaming()
818 ret = video_device_pipeline_start(&csi->vdev, &csi->pipe); in ti_csi2rx_start_streaming()
824 csi->sequence = 0; in ti_csi2rx_start_streaming()
826 spin_lock_irqsave(&dma->lock, flags); in ti_csi2rx_start_streaming()
827 buf = list_entry(dma->queue.next, struct ti_csi2rx_buffer, list); in ti_csi2rx_start_streaming()
831 dev_err(csi->dev, "Failed to start DMA: %d\n", ret); in ti_csi2rx_start_streaming()
832 spin_unlock_irqrestore(&dma->lock, flags); in ti_csi2rx_start_streaming()
836 list_move_tail(&buf->list, &dma->submitted); in ti_csi2rx_start_streaming()
837 dma->state = TI_CSI2RX_DMA_ACTIVE; in ti_csi2rx_start_streaming()
838 spin_unlock_irqrestore(&dma->lock, flags); in ti_csi2rx_start_streaming()
840 ret = v4l2_subdev_call(csi->source, video, s_stream, 1); in ti_csi2rx_start_streaming()
849 video_device_pipeline_stop(&csi->vdev); in ti_csi2rx_start_streaming()
850 writel(0, csi->shim + SHIM_CNTL); in ti_csi2rx_start_streaming()
851 writel(0, csi->shim + SHIM_DMACNTX); in ti_csi2rx_start_streaming()
862 video_device_pipeline_stop(&csi->vdev); in ti_csi2rx_stop_streaming()
864 writel(0, csi->shim + SHIM_CNTL); in ti_csi2rx_stop_streaming()
865 writel(0, csi->shim + SHIM_DMACNTX); in ti_csi2rx_stop_streaming()
867 ret = v4l2_subdev_call(csi->source, video, s_stream, 0); in ti_csi2rx_stop_streaming()
869 dev_err(csi->dev, "Failed to stop subdev stream\n"); in ti_csi2rx_stop_streaming()
887 struct vb2_queue *q = &csi->vidq; in ti_csi2rx_init_vb2q()
890 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; in ti_csi2rx_init_vb2q()
891 q->io_modes = VB2_MMAP | VB2_DMABUF; in ti_csi2rx_init_vb2q()
892 q->drv_priv = csi; in ti_csi2rx_init_vb2q()
893 q->buf_struct_size = sizeof(struct ti_csi2rx_buffer); in ti_csi2rx_init_vb2q()
894 q->ops = &csi_vb2_qops; in ti_csi2rx_init_vb2q()
895 q->mem_ops = &vb2_dma_contig_memops; in ti_csi2rx_init_vb2q()
896 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; in ti_csi2rx_init_vb2q()
897 q->dev = dmaengine_get_dma_device(csi->dma.chan); in ti_csi2rx_init_vb2q()
898 q->lock = &csi->mutex; in ti_csi2rx_init_vb2q()
899 q->min_queued_buffers = 1; in ti_csi2rx_init_vb2q()
905 csi->vdev.queue = q; in ti_csi2rx_init_vb2q()
912 struct media_entity *entity = link->sink->entity; in ti_csi2rx_link_validate()
915 struct v4l2_pix_format *csi_fmt = &csi->v_fmt.fmt.pix; in ti_csi2rx_link_validate()
918 .pad = link->source->index, in ti_csi2rx_link_validate()
923 ret = v4l2_subdev_call_state_active(csi->source, pad, in ti_csi2rx_link_validate()
928 if (source_fmt.format.width != csi_fmt->width) { in ti_csi2rx_link_validate()
929 dev_dbg(csi->dev, "Width does not match (source %u, sink %u)\n", in ti_csi2rx_link_validate()
930 source_fmt.format.width, csi_fmt->width); in ti_csi2rx_link_validate()
931 return -EPIPE; in ti_csi2rx_link_validate()
934 if (source_fmt.format.height != csi_fmt->height) { in ti_csi2rx_link_validate()
935 dev_dbg(csi->dev, "Height does not match (source %u, sink %u)\n", in ti_csi2rx_link_validate()
936 source_fmt.format.height, csi_fmt->height); in ti_csi2rx_link_validate()
937 return -EPIPE; in ti_csi2rx_link_validate()
940 if (source_fmt.format.field != csi_fmt->field && in ti_csi2rx_link_validate()
941 csi_fmt->field != V4L2_FIELD_NONE) { in ti_csi2rx_link_validate()
942 dev_dbg(csi->dev, "Field does not match (source %u, sink %u)\n", in ti_csi2rx_link_validate()
943 source_fmt.format.field, csi_fmt->field); in ti_csi2rx_link_validate()
944 return -EPIPE; in ti_csi2rx_link_validate()
949 dev_dbg(csi->dev, "Media bus format 0x%x not supported\n", in ti_csi2rx_link_validate()
951 return -EPIPE; in ti_csi2rx_link_validate()
954 if (ti_fmt->fourcc != csi_fmt->pixelformat) { in ti_csi2rx_link_validate()
955 dev_dbg(csi->dev, in ti_csi2rx_link_validate()
957 ti_fmt->fourcc, csi_fmt->pixelformat); in ti_csi2rx_link_validate()
958 return -EPIPE; in ti_csi2rx_link_validate()
975 INIT_LIST_HEAD(&csi->dma.queue); in ti_csi2rx_init_dma()
976 INIT_LIST_HEAD(&csi->dma.submitted); in ti_csi2rx_init_dma()
977 spin_lock_init(&csi->dma.lock); in ti_csi2rx_init_dma()
979 csi->dma.state = TI_CSI2RX_DMA_STOPPED; in ti_csi2rx_init_dma()
981 csi->dma.chan = dma_request_chan(csi->dev, "rx0"); in ti_csi2rx_init_dma()
982 if (IS_ERR(csi->dma.chan)) in ti_csi2rx_init_dma()
983 return PTR_ERR(csi->dma.chan); in ti_csi2rx_init_dma()
985 ret = dmaengine_slave_config(csi->dma.chan, &cfg); in ti_csi2rx_init_dma()
987 dma_release_channel(csi->dma.chan); in ti_csi2rx_init_dma()
991 csi->dma.drain.len = DRAIN_BUFFER_SIZE; in ti_csi2rx_init_dma()
992 csi->dma.drain.vaddr = dma_alloc_coherent(csi->dev, csi->dma.drain.len, in ti_csi2rx_init_dma()
993 &csi->dma.drain.paddr, in ti_csi2rx_init_dma()
995 if (!csi->dma.drain.vaddr) in ti_csi2rx_init_dma()
996 return -ENOMEM; in ti_csi2rx_init_dma()
1003 struct media_device *mdev = &csi->mdev; in ti_csi2rx_v4l2_init()
1004 struct video_device *vdev = &csi->vdev; in ti_csi2rx_v4l2_init()
1006 struct v4l2_pix_format *pix_fmt = &csi->v_fmt.fmt.pix; in ti_csi2rx_v4l2_init()
1011 return -EINVAL; in ti_csi2rx_v4l2_init()
1013 pix_fmt->width = 640; in ti_csi2rx_v4l2_init()
1014 pix_fmt->height = 480; in ti_csi2rx_v4l2_init()
1015 pix_fmt->field = V4L2_FIELD_NONE; in ti_csi2rx_v4l2_init()
1016 pix_fmt->colorspace = V4L2_COLORSPACE_SRGB; in ti_csi2rx_v4l2_init()
1017 pix_fmt->ycbcr_enc = V4L2_YCBCR_ENC_601, in ti_csi2rx_v4l2_init()
1018 pix_fmt->quantization = V4L2_QUANTIZATION_LIM_RANGE, in ti_csi2rx_v4l2_init()
1019 pix_fmt->xfer_func = V4L2_XFER_FUNC_SRGB, in ti_csi2rx_v4l2_init()
1021 ti_csi2rx_fill_fmt(fmt, &csi->v_fmt); in ti_csi2rx_v4l2_init()
1023 mdev->dev = csi->dev; in ti_csi2rx_v4l2_init()
1024 mdev->hw_revision = 1; in ti_csi2rx_v4l2_init()
1025 strscpy(mdev->model, "TI-CSI2RX", sizeof(mdev->model)); in ti_csi2rx_v4l2_init()
1029 strscpy(vdev->name, TI_CSI2RX_MODULE_NAME, sizeof(vdev->name)); in ti_csi2rx_v4l2_init()
1030 vdev->v4l2_dev = &csi->v4l2_dev; in ti_csi2rx_v4l2_init()
1031 vdev->vfl_dir = VFL_DIR_RX; in ti_csi2rx_v4l2_init()
1032 vdev->fops = &csi_fops; in ti_csi2rx_v4l2_init()
1033 vdev->ioctl_ops = &csi_ioctl_ops; in ti_csi2rx_v4l2_init()
1034 vdev->release = video_device_release_empty; in ti_csi2rx_v4l2_init()
1035 vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | in ti_csi2rx_v4l2_init()
1037 vdev->lock = &csi->mutex; in ti_csi2rx_v4l2_init()
1040 csi->pad.flags = MEDIA_PAD_FL_SINK; in ti_csi2rx_v4l2_init()
1041 vdev->entity.ops = &ti_csi2rx_video_entity_ops; in ti_csi2rx_v4l2_init()
1042 ret = media_entity_pads_init(&csi->vdev.entity, 1, &csi->pad); in ti_csi2rx_v4l2_init()
1046 csi->v4l2_dev.mdev = mdev; in ti_csi2rx_v4l2_init()
1048 ret = v4l2_device_register(csi->dev, &csi->v4l2_dev); in ti_csi2rx_v4l2_init()
1054 v4l2_device_unregister(&csi->v4l2_dev); in ti_csi2rx_v4l2_init()
1064 dma_free_coherent(csi->dev, csi->dma.drain.len, in ti_csi2rx_cleanup_dma()
1065 csi->dma.drain.vaddr, csi->dma.drain.paddr); in ti_csi2rx_cleanup_dma()
1066 csi->dma.drain.vaddr = NULL; in ti_csi2rx_cleanup_dma()
1067 dma_release_channel(csi->dma.chan); in ti_csi2rx_cleanup_dma()
1072 media_device_unregister(&csi->mdev); in ti_csi2rx_cleanup_v4l2()
1073 v4l2_device_unregister(&csi->v4l2_dev); in ti_csi2rx_cleanup_v4l2()
1074 media_device_cleanup(&csi->mdev); in ti_csi2rx_cleanup_v4l2()
1079 v4l2_async_nf_unregister(&csi->notifier); in ti_csi2rx_cleanup_subdev()
1080 v4l2_async_nf_cleanup(&csi->notifier); in ti_csi2rx_cleanup_subdev()
1085 vb2_queue_release(&csi->vidq); in ti_csi2rx_cleanup_vb2q()
1093 csi = devm_kzalloc(&pdev->dev, sizeof(*csi), GFP_KERNEL); in ti_csi2rx_probe()
1095 return -ENOMEM; in ti_csi2rx_probe()
1097 csi->dev = &pdev->dev; in ti_csi2rx_probe()
1100 mutex_init(&csi->mutex); in ti_csi2rx_probe()
1101 csi->shim = devm_platform_ioremap_resource(pdev, 0); in ti_csi2rx_probe()
1102 if (IS_ERR(csi->shim)) { in ti_csi2rx_probe()
1103 ret = PTR_ERR(csi->shim); in ti_csi2rx_probe()
1123 ret = of_platform_populate(csi->dev->of_node, NULL, NULL, csi->dev); in ti_csi2rx_probe()
1125 dev_err(csi->dev, "Failed to create children: %d\n", ret); in ti_csi2rx_probe()
1140 mutex_destroy(&csi->mutex); in ti_csi2rx_probe()
1148 video_unregister_device(&csi->vdev); in ti_csi2rx_remove()
1155 mutex_destroy(&csi->mutex); in ti_csi2rx_remove()
1159 { .compatible = "ti,j721e-csi2rx-shim", },
1176 MODULE_AUTHOR("Jai Luthra <j-luthra@ti.com>");