// SPDX-License-Identifier: GPL-2.0 /* * Xilinx Video DMA * * Copyright (C) 2013-2015 Ideas on Board * Copyright (C) 2013-2015 Xilinx, Inc. * * Contacts: Hyun Kwon <[email protected]> * Laurent Pinchart <[email protected]> */ #include <linux/dma/xilinx_dma.h> #include <linux/lcm.h> #include <linux/list.h> #include <linux/module.h> #include <linux/of.h> #include <linux/slab.h> #include <media/v4l2-dev.h> #include <media/v4l2-fh.h> #include <media/v4l2-ioctl.h> #include <media/videobuf2-v4l2.h> #include <media/videobuf2-dma-contig.h> #include "xilinx-dma.h" #include "xilinx-vip.h" #include "xilinx-vipp.h" #define XVIP_DMA_DEF_WIDTH … #define XVIP_DMA_DEF_HEIGHT … /* Minimum and maximum widths are expressed in bytes */ #define XVIP_DMA_MIN_WIDTH … #define XVIP_DMA_MAX_WIDTH … #define XVIP_DMA_MIN_HEIGHT … #define XVIP_DMA_MAX_HEIGHT … /* ----------------------------------------------------------------------------- * Helper functions */ static struct v4l2_subdev * xvip_dma_remote_subdev(struct media_pad *local, u32 *pad) { … } static int xvip_dma_verify_format(struct xvip_dma *dma) { … } /* ----------------------------------------------------------------------------- * Pipeline Stream Management */ /** * xvip_pipeline_start_stop - Start ot stop streaming on a pipeline * @pipe: The pipeline * @start: Start (when true) or stop (when false) the pipeline * * Walk the entities chain starting at the pipeline output video node and start * or stop all of them. * * Return: 0 if successful, or the return value of the failed video::s_stream * operation otherwise. */ static int xvip_pipeline_start_stop(struct xvip_pipeline *pipe, bool start) { … } /** * xvip_pipeline_set_stream - Enable/disable streaming on a pipeline * @pipe: The pipeline * @on: Turn the stream on when true or off when false * * The pipeline is shared between all DMA engines connect at its input and * output. While the stream state of DMA engines can be controlled * independently, pipelines have a shared stream state that enable or disable * all entities in the pipeline. For this reason the pipeline uses a streaming * counter that tracks the number of DMA engines that have requested the stream * to be enabled. * * When called with the @on argument set to true, this function will increment * the pipeline streaming count. If the streaming count reaches the number of * DMA engines in the pipeline it will enable all entities that belong to the * pipeline. * * Similarly, when called with the @on argument set to false, this function will * decrement the pipeline streaming count and disable all entities in the * pipeline when the streaming count reaches zero. * * Return: 0 if successful, or the return value of the failed video::s_stream * operation otherwise. Stopping the pipeline never fails. The pipeline state is * not updated when the operation fails. */ static int xvip_pipeline_set_stream(struct xvip_pipeline *pipe, bool on) { … } static int xvip_pipeline_validate(struct xvip_pipeline *pipe, struct xvip_dma *start) { … } static void __xvip_pipeline_cleanup(struct xvip_pipeline *pipe) { … } /** * xvip_pipeline_cleanup - Cleanup the pipeline after streaming * @pipe: the pipeline * * Decrease the pipeline use count and clean it up if we were the last user. */ static void xvip_pipeline_cleanup(struct xvip_pipeline *pipe) { … } /** * xvip_pipeline_prepare - Prepare the pipeline for streaming * @pipe: the pipeline * @dma: DMA engine at one end of the pipeline * * Validate the pipeline if no user exists yet, otherwise just increase the use * count. * * Return: 0 if successful or -EPIPE if the pipeline is not valid. */ static int xvip_pipeline_prepare(struct xvip_pipeline *pipe, struct xvip_dma *dma) { … } /* ----------------------------------------------------------------------------- * videobuf2 queue operations */ /** * struct xvip_dma_buffer - Video DMA buffer * @buf: vb2 buffer base object * @queue: buffer list entry in the DMA engine queued buffers list * @dma: DMA channel that uses the buffer */ struct xvip_dma_buffer { … }; #define to_xvip_dma_buffer(vb) … static void xvip_dma_complete(void *param) { … } static int xvip_dma_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], struct device *alloc_devs[]) { … } static int xvip_dma_buffer_prepare(struct vb2_buffer *vb) { … } static void xvip_dma_buffer_queue(struct vb2_buffer *vb) { … } static int xvip_dma_start_streaming(struct vb2_queue *vq, unsigned int count) { … } static void xvip_dma_stop_streaming(struct vb2_queue *vq) { … } static const struct vb2_ops xvip_dma_queue_qops = …; /* ----------------------------------------------------------------------------- * V4L2 ioctls */ static int xvip_dma_querycap(struct file *file, void *fh, struct v4l2_capability *cap) { … } /* FIXME: without this callback function, some applications are not configured * with correct formats, and it results in frames in wrong format. Whether this * callback needs to be required is not clearly defined, so it should be * clarified through the mailing list. */ static int xvip_dma_enum_format(struct file *file, void *fh, struct v4l2_fmtdesc *f) { … } static int xvip_dma_get_format(struct file *file, void *fh, struct v4l2_format *format) { … } static void __xvip_dma_try_format(struct xvip_dma *dma, struct v4l2_pix_format *pix, const struct xvip_video_format **fmtinfo) { … } static int xvip_dma_try_format(struct file *file, void *fh, struct v4l2_format *format) { … } static int xvip_dma_set_format(struct file *file, void *fh, struct v4l2_format *format) { … } static const struct v4l2_ioctl_ops xvip_dma_ioctl_ops = …; /* ----------------------------------------------------------------------------- * V4L2 file operations */ static const struct v4l2_file_operations xvip_dma_fops = …; /* ----------------------------------------------------------------------------- * Xilinx Video DMA Core */ int xvip_dma_init(struct xvip_composite_device *xdev, struct xvip_dma *dma, enum v4l2_buf_type type, unsigned int port) { … } void xvip_dma_cleanup(struct xvip_dma *dma) { … }