drivers/media/platform/nxp/imx8-isi/imx8-isi-crossbar.c

Source file repositories/reference/linux-study-clean/drivers/media/platform/nxp/imx8-isi/imx8-isi-crossbar.c

File Facts

System
Linux kernel
Corpus path
drivers/media/platform/nxp/imx8-isi/imx8-isi-crossbar.c
Extension
.c
Size
13355 bytes
Lines
508
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

if (ret) {
			dev_err(xbar->isi->dev,
				"failed to enable streams 0x%llx on '%s':%u: %d\n",
				sink_streams, remote_sd->name, remote_pad, ret);
			mxc_isi_crossbar_gasket_disable(xbar, sink_pad);
			return ret;
		}
	}

	input->enable_count++;

	return 0;
}

static int mxc_isi_crossbar_disable_streams(struct v4l2_subdev *sd,
					    struct v4l2_subdev_state *state,
					    u32 pad, u64 streams_mask)
{
	struct mxc_isi_crossbar *xbar = to_isi_crossbar(sd);
	struct v4l2_subdev *remote_sd;
	struct mxc_isi_input *input;
	u64 sink_streams;
	u32 sink_pad;
	u32 remote_pad;
	int ret = 0;

	remote_sd = mxc_isi_crossbar_xlate_streams(xbar, state, pad, streams_mask,
						   &sink_pad, &sink_streams,
						   &remote_pad);
	if (IS_ERR(remote_sd))
		return PTR_ERR(remote_sd);

	input = &xbar->inputs[sink_pad];

	input->enable_count--;

	if (!input->enable_count) {
		ret = v4l2_subdev_disable_streams(remote_sd, remote_pad,
						  sink_streams);
		if (ret)
			dev_err(xbar->isi->dev,
				"failed to disable streams 0x%llx on '%s':%u: %d\n",
				sink_streams, remote_sd->name, remote_pad, ret);

		mxc_isi_crossbar_gasket_disable(xbar, sink_pad);
	}

	return ret;
}

static const struct v4l2_subdev_pad_ops mxc_isi_crossbar_subdev_pad_ops = {
	.enum_mbus_code = mxc_isi_crossbar_enum_mbus_code,
	.get_fmt = v4l2_subdev_get_fmt,
	.set_fmt = mxc_isi_crossbar_set_fmt,
	.set_routing = mxc_isi_crossbar_set_routing,
	.enable_streams = mxc_isi_crossbar_enable_streams,
	.disable_streams = mxc_isi_crossbar_disable_streams,
};

static const struct v4l2_subdev_ops mxc_isi_crossbar_subdev_ops = {
	.pad = &mxc_isi_crossbar_subdev_pad_ops,
};

static const struct v4l2_subdev_internal_ops mxc_isi_crossbar_internal_ops = {
	.init_state = mxc_isi_crossbar_init_state,
};

static const struct media_entity_operations mxc_isi_cross_entity_ops = {
	.get_fwnode_pad = v4l2_subdev_get_fwnode_pad_1_to_1,
	.link_validate	= v4l2_subdev_link_validate,
	.has_pad_interdep = v4l2_subdev_has_pad_interdep,
};

/* -----------------------------------------------------------------------------
 * Init & cleanup
 */

int mxc_isi_crossbar_init(struct mxc_isi_dev *isi)
{
	struct mxc_isi_crossbar *xbar = &isi->crossbar;
	struct v4l2_subdev *sd = &xbar->sd;
	unsigned int num_pads;
	unsigned int i;
	int ret;

	xbar->isi = isi;

	v4l2_subdev_init(sd, &mxc_isi_crossbar_subdev_ops);
	sd->internal_ops = &mxc_isi_crossbar_internal_ops;
	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_STREAMS;

Annotation

Implementation Notes