drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c

Source file repositories/reference/linux-study-clean/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c

File Facts

System
Linux kernel
Corpus path
drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c
Extension
.c
Size
8911 bytes
Lines
355
Domain
Driver Families
Bucket
drivers/media
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct sun4i_csi_traits {
	unsigned int channels;
	unsigned int max_width;
	bool has_isp;
};

static int sun4i_csi_video_link_validate(struct media_link *link)
{
	dev_warn_once(link->graph_obj.mdev->dev,
		      "Driver bug: link validation not implemented\n");
	return 0;
}

static const struct media_entity_operations sun4i_csi_video_entity_ops = {
	.link_validate = sun4i_csi_video_link_validate,
};

static const struct media_entity_operations sun4i_csi_subdev_entity_ops = {
	.link_validate = v4l2_subdev_link_validate,
};

static int sun4i_csi_notify_bound(struct v4l2_async_notifier *notifier,
				  struct v4l2_subdev *subdev,
				  struct v4l2_async_connection *asd)
{
	struct sun4i_csi *csi = container_of(notifier, struct sun4i_csi,
					     notifier);

	csi->src_subdev = subdev;
	csi->src_pad = media_entity_get_fwnode_pad(&subdev->entity,
						   subdev->fwnode,
						   MEDIA_PAD_FL_SOURCE);
	if (csi->src_pad < 0) {
		dev_err(csi->dev, "Couldn't find output pad for subdev %s\n",
			subdev->name);
		return csi->src_pad;
	}

	dev_dbg(csi->dev, "Bound %s pad: %d\n", subdev->name, csi->src_pad);
	return 0;
}

static int sun4i_csi_notify_complete(struct v4l2_async_notifier *notifier)
{
	struct sun4i_csi *csi = container_of(notifier, struct sun4i_csi,
					     notifier);
	struct v4l2_subdev *subdev = &csi->subdev;
	struct video_device *vdev = &csi->vdev;
	int ret;

	ret = v4l2_device_register_subdev(&csi->v4l, subdev);
	if (ret < 0)
		return ret;

	ret = sun4i_csi_v4l2_register(csi);
	if (ret < 0)
		return ret;

	ret = media_device_register(&csi->mdev);
	if (ret)
		return ret;

	/* Create link from subdev to main device */
	ret = media_create_pad_link(&subdev->entity, CSI_SUBDEV_SOURCE,
				    &vdev->entity, 0,
				    MEDIA_LNK_FL_ENABLED |
				    MEDIA_LNK_FL_IMMUTABLE);
	if (ret)
		goto err_clean_media;

	ret = media_create_pad_link(&csi->src_subdev->entity, csi->src_pad,
				    &subdev->entity, CSI_SUBDEV_SINK,
				    MEDIA_LNK_FL_ENABLED |
				    MEDIA_LNK_FL_IMMUTABLE);
	if (ret)
		goto err_clean_media;

	ret = v4l2_device_register_subdev_nodes(&csi->v4l);
	if (ret < 0)
		goto err_clean_media;

	return 0;

err_clean_media:
	media_device_unregister(&csi->mdev);

	return ret;
}

static const struct v4l2_async_notifier_operations sun4i_csi_notify_ops = {

Annotation

Implementation Notes