drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c

Source file repositories/reference/linux-study-clean/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c

File Facts

System
Linux kernel
Corpus path
drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
Extension
.c
Size
22444 bytes
Lines
829
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 rkisp1_isr_data {
	const char *name;
	irqreturn_t (*isr)(int irq, void *ctx);
	u32 line_mask;
};

/* ----------------------------------------------------------------------------
 * Sensor DT bindings
 */

static int rkisp1_subdev_notifier_bound(struct v4l2_async_notifier *notifier,
					struct v4l2_subdev *sd,
					struct v4l2_async_connection *asc)
{
	struct rkisp1_device *rkisp1 =
		container_of(notifier, struct rkisp1_device, notifier);
	struct rkisp1_sensor_async *s_asd =
		container_of(asc, struct rkisp1_sensor_async, asd);
	int source_pad;
	int ret;

	s_asd->sd = sd;

	source_pad = media_entity_get_fwnode_pad(&sd->entity, s_asd->source_ep,
						 MEDIA_PAD_FL_SOURCE);
	if (source_pad < 0) {
		dev_err(rkisp1->dev, "failed to find source pad for %s\n",
			sd->name);
		return source_pad;
	}

	if (s_asd->port == 0)
		return rkisp1_csi_link_sensor(rkisp1, sd, s_asd, source_pad);

	ret = media_create_pad_link(&sd->entity, source_pad,
				    &rkisp1->isp.sd.entity,
				    RKISP1_ISP_PAD_SINK_VIDEO,
				    !s_asd->index ? MEDIA_LNK_FL_ENABLED : 0);
	if (ret) {
		dev_err(rkisp1->dev, "failed to link source pad of %s\n",
			sd->name);
		return ret;
	}

	return 0;
}

static int rkisp1_subdev_notifier_complete(struct v4l2_async_notifier *notifier)
{
	struct rkisp1_device *rkisp1 =
		container_of(notifier, struct rkisp1_device, notifier);

	return v4l2_device_register_subdev_nodes(&rkisp1->v4l2_dev);
}

static void rkisp1_subdev_notifier_destroy(struct v4l2_async_connection *asc)
{
	struct rkisp1_sensor_async *rk_asd =
		container_of(asc, struct rkisp1_sensor_async, asd);

	fwnode_handle_put(rk_asd->source_ep);
}

static const struct v4l2_async_notifier_operations rkisp1_subdev_notifier_ops = {
	.bound = rkisp1_subdev_notifier_bound,
	.complete = rkisp1_subdev_notifier_complete,
	.destroy = rkisp1_subdev_notifier_destroy,
};

static int rkisp1_subdev_notifier_register(struct rkisp1_device *rkisp1)
{
	struct v4l2_async_notifier *ntf = &rkisp1->notifier;
	struct fwnode_handle *fwnode = dev_fwnode(rkisp1->dev);
	struct fwnode_handle *ep;
	unsigned int index = 0;
	int ret = 0;

	v4l2_async_nf_init(ntf, &rkisp1->v4l2_dev);

	ntf->ops = &rkisp1_subdev_notifier_ops;

	fwnode_graph_for_each_endpoint(fwnode, ep) {
		struct fwnode_handle *port;
		struct v4l2_fwnode_endpoint vep = { };
		struct rkisp1_sensor_async *rk_asd;
		struct fwnode_handle *source;
		u32 reg = 0;

		/* Select the bus type based on the port. */
		port = fwnode_get_parent(ep);

Annotation

Implementation Notes