drivers/media/platform/sunxi/sun4i-csi/sun4i_dma.c

Source file repositories/reference/linux-study-clean/drivers/media/platform/sunxi/sun4i-csi/sun4i_dma.c

File Facts

System
Linux kernel
Corpus path
drivers/media/platform/sunxi/sun4i-csi/sun4i_dma.c
Extension
.c
Size
11562 bytes
Lines
459
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 sun4i_csi_buffer {
	struct vb2_v4l2_buffer	vb;
	struct list_head	list;
};

static inline struct sun4i_csi_buffer *
vb2_v4l2_to_csi_buffer(const struct vb2_v4l2_buffer *p)
{
	return container_of(p, struct sun4i_csi_buffer, vb);
}

static inline struct sun4i_csi_buffer *
vb2_to_csi_buffer(const struct vb2_buffer *p)
{
	return vb2_v4l2_to_csi_buffer(to_vb2_v4l2_buffer(p));
}

static void sun4i_csi_capture_start(struct sun4i_csi *csi)
{
	writel(CSI_CPT_CTRL_VIDEO_START, csi->regs + CSI_CPT_CTRL_REG);
}

static void sun4i_csi_capture_stop(struct sun4i_csi *csi)
{
	writel(0, csi->regs + CSI_CPT_CTRL_REG);
}

static int sun4i_csi_queue_setup(struct vb2_queue *vq,
				 unsigned int *nbuffers,
				 unsigned int *nplanes,
				 unsigned int sizes[],
				 struct device *alloc_devs[])
{
	struct sun4i_csi *csi = vb2_get_drv_priv(vq);
	unsigned int num_planes = csi->fmt.num_planes;
	unsigned int i;

	if (*nplanes) {
		if (*nplanes != num_planes)
			return -EINVAL;

		for (i = 0; i < num_planes; i++)
			if (sizes[i] < csi->fmt.plane_fmt[i].sizeimage)
				return -EINVAL;
		return 0;
	}

	*nplanes = num_planes;
	for (i = 0; i < num_planes; i++)
		sizes[i] = csi->fmt.plane_fmt[i].sizeimage;

	return 0;
};

static int sun4i_csi_buffer_prepare(struct vb2_buffer *vb)
{
	struct sun4i_csi *csi = vb2_get_drv_priv(vb->vb2_queue);
	unsigned int i;

	for (i = 0; i < csi->fmt.num_planes; i++) {
		unsigned long size = csi->fmt.plane_fmt[i].sizeimage;

		if (vb2_plane_size(vb, i) < size) {
			dev_err(csi->dev, "buffer too small (%lu < %lu)\n",
				vb2_plane_size(vb, i), size);
			return -EINVAL;
		}

		vb2_set_plane_payload(vb, i, size);
	}

	return 0;
}

static int sun4i_csi_setup_scratch_buffer(struct sun4i_csi *csi,
					  unsigned int slot)
{
	dma_addr_t addr = csi->scratch.paddr;
	unsigned int plane;

	dev_dbg(csi->dev,
		"No more available buffer, using the scratch buffer\n");

	for (plane = 0; plane < csi->fmt.num_planes; plane++) {
		writel(addr, csi->regs + CSI_BUF_ADDR_REG(plane, slot));
		addr += csi->fmt.plane_fmt[plane].sizeimage;
	}

	csi->current_buf[slot] = NULL;
	return 0;

Annotation

Implementation Notes