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

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

File Facts

System
Linux kernel
Corpus path
drivers/media/platform/rockchip/rkisp1/rkisp1-csi.c
Extension
.c
Size
13464 bytes
Lines
519
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 (rkisp1->csi.is_dphy_errctrl_disabled) {
			val = rkisp1_read(rkisp1, RKISP1_CIF_MIPI_IMSC);
			val |= RKISP1_CIF_MIPI_ERR_CTRL(0x0f);
			rkisp1_write(rkisp1, RKISP1_CIF_MIPI_IMSC, val);
			rkisp1->csi.is_dphy_errctrl_disabled = false;
		}
	} else {
		rkisp1->debug.mipi_error++;
	}

	return IRQ_HANDLED;
}

/* ----------------------------------------------------------------------------
 * Subdev pad operations
 */

static int rkisp1_csi_enum_mbus_code(struct v4l2_subdev *sd,
				     struct v4l2_subdev_state *sd_state,
				     struct v4l2_subdev_mbus_code_enum *code)
{
	unsigned int i;
	int pos = 0;

	if (code->pad == RKISP1_CSI_PAD_SRC) {
		const struct v4l2_mbus_framefmt *sink_fmt;

		if (code->index)
			return -EINVAL;

		sink_fmt = v4l2_subdev_state_get_format(sd_state,
							RKISP1_CSI_PAD_SINK);
		code->code = sink_fmt->code;

		return 0;
	}

	for (i = 0; ; i++) {
		const struct rkisp1_mbus_info *fmt =
			rkisp1_mbus_info_get_by_index(i);

		if (!fmt)
			return -EINVAL;

		if (!(fmt->direction & RKISP1_ISP_SD_SINK))
			continue;

		if (code->index == pos) {
			code->code = fmt->mbus_code;
			return 0;
		}

		pos++;
	}

	return -EINVAL;
}

static int rkisp1_csi_init_state(struct v4l2_subdev *sd,
				 struct v4l2_subdev_state *sd_state)
{
	struct v4l2_mbus_framefmt *sink_fmt, *src_fmt;

	sink_fmt = v4l2_subdev_state_get_format(sd_state, RKISP1_CSI_PAD_SINK);
	src_fmt = v4l2_subdev_state_get_format(sd_state, RKISP1_CSI_PAD_SRC);

	sink_fmt->width = RKISP1_DEFAULT_WIDTH;
	sink_fmt->height = RKISP1_DEFAULT_HEIGHT;
	sink_fmt->field = V4L2_FIELD_NONE;
	sink_fmt->code = RKISP1_CSI_DEF_FMT;

	*src_fmt = *sink_fmt;

	return 0;
}

static int rkisp1_csi_set_fmt(struct v4l2_subdev *sd,
			      struct v4l2_subdev_state *sd_state,
			      struct v4l2_subdev_format *fmt)
{
	struct rkisp1_csi *csi = to_rkisp1_csi(sd);
	const struct rkisp1_mbus_info *mbus_info;
	struct v4l2_mbus_framefmt *sink_fmt, *src_fmt;

	/* The format on the source pad always matches the sink pad. */
	if (fmt->pad == RKISP1_CSI_PAD_SRC)
		return v4l2_subdev_get_fmt(sd, sd_state, fmt);

	sink_fmt = v4l2_subdev_state_get_format(sd_state, RKISP1_CSI_PAD_SINK);

Annotation

Implementation Notes