linux/drivers/staging/media/imx/imx-media-csi.c

// SPDX-License-Identifier: GPL-2.0+
/*
 * V4L2 Capture CSI Subdev for Freescale i.MX5/6 SOC
 *
 * Copyright (c) 2014-2017 Mentor Graphics Inc.
 * Copyright (C) 2017 Pengutronix, Philipp Zabel <[email protected]>
 */
#include <linux/delay.h>
#include <linux/gcd.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/of_graph.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-mc.h>
#include <media/v4l2-subdev.h>
#include <media/videobuf2-dma-contig.h>
#include <video/imx-ipu-v3.h>
#include <media/imx.h>
#include "imx-media.h"

/*
 * Min/Max supported width and heights.
 *
 * We allow planar output, so we have to align width by 16 pixels
 * to meet IDMAC alignment requirements.
 *
 * TODO: move this into pad format negotiation, if capture device
 * has not requested planar formats, we should allow 8 pixel
 * alignment.
 */
#define MIN_W
#define MIN_H
#define MAX_W
#define MAX_H
#define W_ALIGN
#define H_ALIGN
#define S_ALIGN

/*
 * struct csi_skip_desc - CSI frame skipping descriptor
 * @keep - number of frames kept per max_ratio frames
 * @max_ratio - width of skip_smfc, written to MAX_RATIO bitfield
 * @skip_smfc - skip pattern written to the SKIP_SMFC bitfield
 */
struct csi_skip_desc {};

struct csi_priv {};

static inline struct csi_priv *sd_to_dev(struct v4l2_subdev *sdev)
{}

static inline struct csi_priv *notifier_to_dev(struct v4l2_async_notifier *n)
{}

static inline bool is_parallel_bus(struct v4l2_mbus_config *mbus_cfg)
{}

static inline bool is_parallel_16bit_bus(struct v4l2_mbus_config *mbus_cfg)
{}

/*
 * Check for conditions that require the IPU to handle the
 * data internally as generic data, aka passthrough mode:
 * - raw bayer media bus formats, or
 * - BT.656 and BT.1120 (8/10-bit YUV422) data can always be processed
 *   on-the-fly
 * - the CSI is receiving from a 16-bit parallel bus, or
 * - the CSI is receiving from an 8-bit parallel bus and the incoming
 *   media bus format is other than UYVY8_2X8/YUYV8_2X8.
 */
static inline bool requires_passthrough(struct v4l2_mbus_config *mbus_cfg,
					struct v4l2_mbus_framefmt *infmt,
					const struct imx_media_pixfmt *incc)
{}

/*
 * Queries the media bus config of the upstream entity that provides data to
 * the CSI. This will either be the entity directly upstream from the CSI-2
 * receiver, directly upstream from a video mux, or directly upstream from
 * the CSI itself.
 */
static int csi_get_upstream_mbus_config(struct csi_priv *priv,
					struct v4l2_mbus_config *mbus_cfg)
{}

static void csi_idmac_put_ipu_resources(struct csi_priv *priv)
{}

static int csi_idmac_get_ipu_resources(struct csi_priv *priv)
{}

static void csi_vb2_buf_done(struct csi_priv *priv)
{}

static irqreturn_t csi_idmac_eof_interrupt(int irq, void *dev_id)
{}

static irqreturn_t csi_idmac_nfb4eof_interrupt(int irq, void *dev_id)
{}

/*
 * EOF timeout timer function. This is an unrecoverable condition
 * without a stream restart.
 */
static void csi_idmac_eof_timeout(struct timer_list *t)
{}

static void csi_idmac_setup_vb2_buf(struct csi_priv *priv, dma_addr_t *phys)
{}

static void csi_idmac_unsetup_vb2_buf(struct csi_priv *priv,
				      enum vb2_buffer_state return_status)
{}

/* init the SMFC IDMAC channel */
static int csi_idmac_setup_channel(struct csi_priv *priv)
{}

static void csi_idmac_unsetup(struct csi_priv *priv,
			      enum vb2_buffer_state state)
{}

static int csi_idmac_setup(struct csi_priv *priv)
{}

static int csi_idmac_start(struct csi_priv *priv)
{}

static void csi_idmac_wait_last_eof(struct csi_priv *priv)
{}

static void csi_idmac_stop(struct csi_priv *priv)
{}

/* Update the CSI whole sensor and active windows */
static int csi_setup(struct csi_priv *priv)
{}

static int csi_start(struct csi_priv *priv)
{}

static void csi_stop(struct csi_priv *priv)
{}

static const struct csi_skip_desc csi_skip[12] =;

static void csi_apply_skip_interval(const struct csi_skip_desc *skip,
				    struct v4l2_fract *interval)
{}

/*
 * Find the skip pattern to produce the output frame interval closest to the
 * requested one, for the given input frame interval. Updates the output frame
 * interval to the exact value.
 */
static const struct csi_skip_desc *csi_find_best_skip(struct v4l2_fract *in,
						      struct v4l2_fract *out)
{}

/*
 * V4L2 subdev operations.
 */

static int csi_get_frame_interval(struct v4l2_subdev *sd,
				  struct v4l2_subdev_state *sd_state,
				  struct v4l2_subdev_frame_interval *fi)
{}

static int csi_set_frame_interval(struct v4l2_subdev *sd,
				  struct v4l2_subdev_state *sd_state,
				  struct v4l2_subdev_frame_interval *fi)
{}

static int csi_s_stream(struct v4l2_subdev *sd, int enable)
{}

static int csi_link_setup(struct media_entity *entity,
			  const struct media_pad *local,
			  const struct media_pad *remote, u32 flags)
{}

static int csi_link_validate(struct v4l2_subdev *sd,
			     struct media_link *link,
			     struct v4l2_subdev_format *source_fmt,
			     struct v4l2_subdev_format *sink_fmt)
{}

static struct v4l2_mbus_framefmt *
__csi_get_fmt(struct csi_priv *priv, struct v4l2_subdev_state *sd_state,
	      unsigned int pad, enum v4l2_subdev_format_whence which)
{}

static struct v4l2_rect *
__csi_get_crop(struct csi_priv *priv, struct v4l2_subdev_state *sd_state,
	       enum v4l2_subdev_format_whence which)
{}

static struct v4l2_rect *
__csi_get_compose(struct csi_priv *priv, struct v4l2_subdev_state *sd_state,
		  enum v4l2_subdev_format_whence which)
{}

static void csi_try_crop(struct csi_priv *priv,
			 struct v4l2_rect *crop,
			 struct v4l2_subdev_state *sd_state,
			 struct v4l2_mbus_framefmt *infmt,
			 struct v4l2_mbus_config *mbus_cfg)
{}

static int csi_enum_mbus_code(struct v4l2_subdev *sd,
			      struct v4l2_subdev_state *sd_state,
			      struct v4l2_subdev_mbus_code_enum *code)
{}

static int csi_enum_frame_size(struct v4l2_subdev *sd,
			       struct v4l2_subdev_state *sd_state,
			       struct v4l2_subdev_frame_size_enum *fse)
{}

static int csi_enum_frame_interval(struct v4l2_subdev *sd,
				   struct v4l2_subdev_state *sd_state,
				   struct v4l2_subdev_frame_interval_enum *fie)
{}

static int csi_get_fmt(struct v4l2_subdev *sd,
		       struct v4l2_subdev_state *sd_state,
		       struct v4l2_subdev_format *sdformat)
{}

static void csi_try_field(struct csi_priv *priv,
			  struct v4l2_subdev_state *sd_state,
			  struct v4l2_subdev_format *sdformat)
{}

static void csi_try_fmt(struct csi_priv *priv,
			struct v4l2_mbus_config *mbus_cfg,
			struct v4l2_subdev_state *sd_state,
			struct v4l2_subdev_format *sdformat,
			struct v4l2_rect *crop,
			struct v4l2_rect *compose,
			const struct imx_media_pixfmt **cc)
{}

static int csi_set_fmt(struct v4l2_subdev *sd,
		       struct v4l2_subdev_state *sd_state,
		       struct v4l2_subdev_format *sdformat)
{}

static int csi_get_selection(struct v4l2_subdev *sd,
			     struct v4l2_subdev_state *sd_state,
			     struct v4l2_subdev_selection *sel)
{}

static int csi_set_scale(u32 *compose, u32 crop, u32 flags)
{}

static int csi_set_selection(struct v4l2_subdev *sd,
			     struct v4l2_subdev_state *sd_state,
			     struct v4l2_subdev_selection *sel)
{}

static int csi_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
			       struct v4l2_event_subscription *sub)
{}

static int csi_unsubscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
				 struct v4l2_event_subscription *sub)
{}

static int csi_registered(struct v4l2_subdev *sd)
{}

static void csi_unregistered(struct v4l2_subdev *sd)
{}

/*
 * The CSI has only one fwnode endpoint, at the sink pad. Verify the
 * endpoint belongs to us, and return CSI_SINK_PAD.
 */
static int csi_get_fwnode_pad(struct media_entity *entity,
			      struct fwnode_endpoint *endpoint)
{}

static const struct media_entity_operations csi_entity_ops =;

static const struct v4l2_subdev_core_ops csi_core_ops =;

static const struct v4l2_subdev_video_ops csi_video_ops =;

static const struct v4l2_subdev_pad_ops csi_pad_ops =;

static const struct v4l2_subdev_ops csi_subdev_ops =;

static const struct v4l2_subdev_internal_ops csi_internal_ops =;

static int imx_csi_notify_bound(struct v4l2_async_notifier *notifier,
				struct v4l2_subdev *sd,
				struct v4l2_async_connection *asd)
{}

static const struct v4l2_async_notifier_operations csi_notify_ops =;

static int imx_csi_async_register(struct csi_priv *priv)
{}

static int imx_csi_probe(struct platform_device *pdev)
{}

static void imx_csi_remove(struct platform_device *pdev)
{}

static const struct platform_device_id imx_csi_ids[] =;
MODULE_DEVICE_TABLE(platform, imx_csi_ids);

static struct platform_driver imx_csi_driver =;
module_platform_driver();

MODULE_DESCRIPTION();
MODULE_AUTHOR();
MODULE_LICENSE();