drivers/media/v4l2-core/v4l2-subdev.c

Source file repositories/reference/linux-study-clean/drivers/media/v4l2-core/v4l2-subdev.c

File Facts

System
Linux kernel
Corpus path
drivers/media/v4l2-core/v4l2-subdev.c
Extension
.c
Size
71743 bytes
Lines
2764
Domain
Driver Families
Bucket
drivers/media
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 v4l2_subdev_stream_config {
	u32 pad;
	u32 stream;
	bool enabled;

	struct v4l2_mbus_framefmt fmt;
	struct v4l2_rect crop;
	struct v4l2_rect compose;
	struct v4l2_fract interval;
};

#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
/*
 * The Streams API is an experimental feature. To use the Streams API, set
 * 'v4l2_subdev_enable_streams_api' to 1 below.
 */

static bool v4l2_subdev_enable_streams_api;
#endif

/*
 * Maximum stream ID is 63 for now, as we use u64 bitmask to represent a set
 * of streams.
 *
 * Note that V4L2_FRAME_DESC_ENTRY_MAX is related: V4L2_FRAME_DESC_ENTRY_MAX
 * restricts the total number of streams in a pad, although the stream ID is
 * not restricted.
 */
#define V4L2_SUBDEV_MAX_STREAM_ID 63

#include "v4l2-subdev-priv.h"

#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
static int subdev_fh_init(struct v4l2_subdev_fh *fh, struct v4l2_subdev *sd)
{
	struct v4l2_subdev_state *state;
	static struct lock_class_key key;

	state = __v4l2_subdev_state_alloc(sd, "fh->state->lock", &key);
	if (IS_ERR(state))
		return PTR_ERR(state);

	fh->state = state;

	return 0;
}

static void subdev_fh_free(struct v4l2_subdev_fh *fh)
{
	__v4l2_subdev_state_free(fh->state);
	fh->state = NULL;
}

static int subdev_open(struct file *file)
{
	struct video_device *vdev = video_devdata(file);
	struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
	struct v4l2_subdev_fh *subdev_fh;
	int ret;

	subdev_fh = kzalloc_obj(*subdev_fh);
	if (subdev_fh == NULL)
		return -ENOMEM;

	ret = subdev_fh_init(subdev_fh, sd);
	if (ret) {
		kfree(subdev_fh);
		return ret;
	}

	v4l2_fh_init(&subdev_fh->vfh, vdev);
	v4l2_fh_add(&subdev_fh->vfh, file);

	if (sd->v4l2_dev->mdev && sd->entity.graph_obj.mdev->dev) {
		struct module *owner;

		owner = sd->entity.graph_obj.mdev->dev->driver->owner;
		if (!try_module_get(owner)) {
			ret = -EBUSY;
			goto err;
		}
		subdev_fh->owner = owner;
	}

	if (sd->internal_ops && sd->internal_ops->open) {
		ret = sd->internal_ops->open(sd, subdev_fh);
		if (ret < 0)
			goto err;
	}

Annotation

Implementation Notes