drivers/media/pci/mgb4/mgb4_vout.c

Source file repositories/reference/linux-study-clean/drivers/media/pci/mgb4/mgb4_vout.c

File Facts

System
Linux kernel
Corpus path
drivers/media/pci/mgb4/mgb4_vout.c
Extension
.c
Size
24760 bytes
Lines
874
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 (config & (1U << 20)) {
			f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709;
		} else {
			if (config & (1U << 19))
				f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
			else
				f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
		}
		f->fmt.pix.bytesperline = (f->fmt.pix.width + voutdev->padding) * 2;
	} else {
		f->fmt.pix.pixelformat = V4L2_PIX_FMT_ABGR32;
		f->fmt.pix.colorspace = V4L2_COLORSPACE_RAW;
		f->fmt.pix.bytesperline = (f->fmt.pix.width + voutdev->padding) * 4;
	}

	f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height;

	return 0;
}

static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
{
	struct mgb4_vout_dev *voutdev = video_drvdata(file);
	struct mgb4_regs *video = &voutdev->mgbdev->video;
	u32 pixelsize;

	f->fmt.pix.width = voutdev->width;
	f->fmt.pix.height = voutdev->height;
	f->fmt.pix.field = V4L2_FIELD_NONE;

	if (has_yuv(video) && f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) {
		pixelsize = 2;
		if (!(f->fmt.pix.colorspace == V4L2_COLORSPACE_REC709 ||
		      f->fmt.pix.colorspace == V4L2_COLORSPACE_SMPTE170M))
			f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
	} else {
		pixelsize = 4;
		f->fmt.pix.pixelformat = V4L2_PIX_FMT_ABGR32;
		f->fmt.pix.colorspace = V4L2_COLORSPACE_RAW;
	}

	if (f->fmt.pix.bytesperline > f->fmt.pix.width * pixelsize &&
	    f->fmt.pix.bytesperline < f->fmt.pix.width * pixelsize * 2)
		f->fmt.pix.bytesperline = ALIGN(f->fmt.pix.bytesperline,
						pixelsize);
	else
		f->fmt.pix.bytesperline = f->fmt.pix.width * pixelsize;
	f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height;

	return 0;
}

static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
{
	struct mgb4_vout_dev *voutdev = video_drvdata(file);
	struct mgb4_regs *video = &voutdev->mgbdev->video;
	u32 config, pixelsize;
	int ret;

	if (vb2_is_busy(&voutdev->queue))
		return -EBUSY;

	ret = vidioc_try_fmt(file, priv, f);
	if (ret < 0)
		return ret;

	config = mgb4_read_reg(video, voutdev->config->regs.config);
	if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) {
		pixelsize = 2;
		config |= 1U << 16;

		if (f->fmt.pix.colorspace == V4L2_COLORSPACE_REC709) {
			config |= 1U << 20;
			config |= 1U << 19;
		} else if (f->fmt.pix.colorspace == V4L2_COLORSPACE_SMPTE170M) {
			config &= ~(1U << 20);
			config |= 1U << 19;
		} else {
			config &= ~(1U << 20);
			config &= ~(1U << 19);
		}
	} else {
		pixelsize = 4;
		config &= ~(1U << 16);
	}
	mgb4_write_reg(video, voutdev->config->regs.config, config);

	voutdev->padding = (f->fmt.pix.bytesperline - (f->fmt.pix.width
			    * pixelsize)) / pixelsize;

Annotation

Implementation Notes