drivers/media/platform/video-mux.c

Source file repositories/reference/linux-study-clean/drivers/media/platform/video-mux.c

File Facts

System
Linux kernel
Corpus path
drivers/media/platform/video-mux.c
Extension
.c
Size
13730 bytes
Lines
502
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 video_mux {
	struct v4l2_subdev subdev;
	struct v4l2_async_notifier notifier;
	struct media_pad *pads;
	struct mux_control *mux;
	struct mutex lock;
	int active;
};

static const struct v4l2_mbus_framefmt video_mux_format_mbus_default = {
	.width = 1,
	.height = 1,
	.code = MEDIA_BUS_FMT_Y8_1X8,
	.field = V4L2_FIELD_NONE,
};

static inline struct video_mux *
notifier_to_video_mux(struct v4l2_async_notifier *n)
{
	return container_of(n, struct video_mux, notifier);
}

static inline struct video_mux *v4l2_subdev_to_video_mux(struct v4l2_subdev *sd)
{
	return container_of(sd, struct video_mux, subdev);
}

static int video_mux_link_setup(struct media_entity *entity,
				const struct media_pad *local,
				const struct media_pad *remote, u32 flags)
{
	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
	struct v4l2_subdev_state *sd_state;
	struct video_mux *vmux = v4l2_subdev_to_video_mux(sd);
	u16 source_pad = entity->num_pads - 1;
	int ret = 0;

	/*
	 * The mux state is determined by the enabled sink pad link.
	 * Enabling or disabling the source pad link has no effect.
	 */
	if (local->flags & MEDIA_PAD_FL_SOURCE)
		return 0;

	dev_dbg(sd->dev, "link setup '%s':%d->'%s':%d[%d]",
		remote->entity->name, remote->index, local->entity->name,
		local->index, flags & MEDIA_LNK_FL_ENABLED);

	sd_state = v4l2_subdev_lock_and_get_active_state(sd);
	mutex_lock(&vmux->lock);

	if (flags & MEDIA_LNK_FL_ENABLED) {
		struct v4l2_mbus_framefmt *source_mbusformat;

		if (vmux->active == local->index)
			goto out;

		if (vmux->active >= 0) {
			ret = -EBUSY;
			goto out;
		}

		dev_dbg(sd->dev, "setting %d active\n", local->index);
		ret = mux_control_try_select(vmux->mux, local->index);
		if (ret < 0)
			goto out;
		vmux->active = local->index;

		/* Propagate the active format to the source */
		source_mbusformat = v4l2_subdev_state_get_format(sd_state,
								 source_pad);
		*source_mbusformat = *v4l2_subdev_state_get_format(sd_state,
								   vmux->active);
	} else {
		if (vmux->active != local->index)
			goto out;

		dev_dbg(sd->dev, "going inactive\n");
		mux_control_deselect(vmux->mux);
		vmux->active = -1;
	}

out:
	mutex_unlock(&vmux->lock);
	v4l2_subdev_unlock_state(sd_state);
	return ret;
}

static const struct media_entity_operations video_mux_ops = {
	.link_setup = video_mux_link_setup,

Annotation

Implementation Notes