drivers/staging/media/tegra-video/tegra20.c

Source file repositories/reference/linux-study-clean/drivers/staging/media/tegra-video/tegra20.c

File Facts

System
Linux kernel
Corpus path
drivers/staging/media/tegra-video/tegra20.c
Extension
.c
Size
43460 bytes
Lines
1266
Domain
Driver Families
Bucket
drivers/staging
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 (chan->vflip) {
			chan->start_offset   += stride * (height - 1);
			chan->start_offset_u += (stride / 2) * ((height / 2) - 1);
			chan->start_offset_v += (stride / 2) * ((height / 2) - 1);
		}
		if (chan->hflip) {
			chan->start_offset   += stride - 1;
			chan->start_offset_u += (stride / 2) - 1;
			chan->start_offset_v += (stride / 2) - 1;
		}
		break;
	}
}

static void release_buffer(struct tegra_vi_channel *chan,
			   struct tegra_channel_buffer *buf,
			   enum vb2_buffer_state state)
{
	struct vb2_v4l2_buffer *vb = &buf->buf;

	vb->sequence = chan->sequence++;
	vb->field = V4L2_FIELD_NONE;
	vb->vb2_buf.timestamp = ktime_get_ns();
	vb2_buffer_done(&vb->vb2_buf, state);
}

static void tegra20_channel_vi_buffer_setup(struct tegra_vi_channel *chan,
					    struct tegra_channel_buffer *buf)
{
	dma_addr_t base = buf->addr;

	switch (chan->fmtinfo->fourcc) {
	case V4L2_PIX_FMT_YUV420:
	case V4L2_PIX_FMT_YVU420:
		tegra20_vi_write(chan, TEGRA_VI_VB0_BASE_ADDRESS_U,  base + chan->addr_offset_u);
		tegra20_vi_write(chan, TEGRA_VI_VB0_START_ADDRESS_U, base + chan->start_offset_u);
		tegra20_vi_write(chan, TEGRA_VI_VB0_BASE_ADDRESS_V,  base + chan->addr_offset_v);
		tegra20_vi_write(chan, TEGRA_VI_VB0_START_ADDRESS_V, base + chan->start_offset_v);
		fallthrough;

	case V4L2_PIX_FMT_UYVY:
	case V4L2_PIX_FMT_VYUY:
	case V4L2_PIX_FMT_YUYV:
	case V4L2_PIX_FMT_YVYU:
		tegra20_vi_write(chan, TEGRA_VI_VB0_BASE_ADDRESS(TEGRA_VI_OUT_1),  base);
		tegra20_vi_write(chan, TEGRA_VI_VB0_START_ADDRESS(TEGRA_VI_OUT_1), base + chan->start_offset);
		break;
	/* RAW8 */
	case V4L2_PIX_FMT_SRGGB8:
	case V4L2_PIX_FMT_SGRBG8:
	case V4L2_PIX_FMT_SGBRG8:
	case V4L2_PIX_FMT_SBGGR8:
	/* RAW10 */
	case V4L2_PIX_FMT_SRGGB10:
	case V4L2_PIX_FMT_SGRBG10:
	case V4L2_PIX_FMT_SGBRG10:
	case V4L2_PIX_FMT_SBGGR10:
		tegra20_vi_write(chan, TEGRA_VI_VB0_BASE_ADDRESS(TEGRA_VI_OUT_2),  base);
		tegra20_vi_write(chan, TEGRA_VI_VB0_START_ADDRESS(TEGRA_VI_OUT_2), base + chan->start_offset);
		break;
	}
}

static int tegra20_channel_capture_frame(struct tegra_vi_channel *chan,
					 struct tegra_channel_buffer *buf,
					 struct tegra_csi_channel *csi_chan)
{
	u32 val;
	int err;

	tegra20_channel_vi_buffer_setup(chan, buf);

	if (csi_chan) {
		u32 port = csi_chan->csi_port_nums[0] & 1;

		tegra20_csi_write(csi_chan, TEGRA_CSI_PIXEL_STREAM_PP_COMMAND(port),
				  CSI_PP_START_MARKER_FRAME_MAX(0xf) |
				  CSI_PP_SINGLE_SHOT | CSI_PP_ENABLE);

		/*
		 * ERESTARTSYS workaround for syncpoints is used because host1x_syncpt_wait
		 * is unconditionally interruptible. This is not an issue with single shots
		 * or low resolution capture, but -ERESTARTSYS occurs quite often with high
		 * resolution or high framerate captures and if not addressed here will
		 * cause capture to fail entirely.
		 *
		 * TODO: once uninterruptible version of host1x_syncpt_wait is available,
		 * host1x_syncpt_wait should be swapped and ERESTARTSYS workaround can be
		 * removed.
		 */

Annotation

Implementation Notes