Buildroot-YuzukiSBC/buildroot/board/allwinner/suniv-f1c100s/patch/linux/0005-Add-sun4i-csi-packed-format.patch
YuzukiTsuru 91d414c5ad rename
2022-02-17 00:00:03 +08:00

215 lines
7.0 KiB
Diff

---
.../platform/sunxi/sun4i-csi/sun4i_csi.c | 6 +
.../platform/sunxi/sun4i-csi/sun4i_csi.h | 3 +
.../platform/sunxi/sun4i-csi/sun4i_dma.c | 6 +-
.../platform/sunxi/sun4i-csi/sun4i_v4l2.c | 117 +++++++++++++++++-
4 files changed, 129 insertions(+), 3 deletions(-)
diff --git a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c
index b8b07c1de..e0ecf1b7d 100644
--- a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c
+++ b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c
@@ -217,6 +217,12 @@ static int sun4i_csi_probe(struct platform_device *pdev)
return PTR_ERR(csi->rst);
}
+ csi->packed = false;
+ if (device_property_present(&pdev->dev, "packed-format")) {
+ dev_info(&pdev->dev, "Packed (RAW) format enabled.");
+ csi->packed = true;
+ }
+
/* Initialize subdev */
v4l2_subdev_init(subdev, &sun4i_csi_subdev_ops);
subdev->flags = V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
diff --git a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.h b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.h
index 88d39b355..7caf0f940 100644
--- a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.h
+++ b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.h
@@ -150,6 +150,9 @@ struct sun4i_csi {
struct list_head buf_list;
spinlock_t qlock;
unsigned int sequence;
+
+ /* Hack */
+ bool packed;
};
int sun4i_csi_dma_register(struct sun4i_csi *csi, int irq);
diff --git a/drivers/media/platform/sunxi/sun4i-csi/sun4i_dma.c b/drivers/media/platform/sunxi/sun4i-csi/sun4i_dma.c
index 78fa1c535..e2bc9af8c 100644
--- a/drivers/media/platform/sunxi/sun4i-csi/sun4i_dma.c
+++ b/drivers/media/platform/sunxi/sun4i-csi/sun4i_dma.c
@@ -412,7 +412,11 @@ int sun4i_csi_dma_register(struct sun4i_csi *csi, int irq)
csi->current_buf[i] = NULL;
q->min_buffers_needed = 3;
- q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ if (!csi->packed) {
+ q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ } else {
+ q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ }
q->io_modes = VB2_MMAP;
q->lock = &csi->lock;
q->drv_priv = csi;
diff --git a/drivers/media/platform/sunxi/sun4i-csi/sun4i_v4l2.c b/drivers/media/platform/sunxi/sun4i-csi/sun4i_v4l2.c
index 83a3a0257..373f83037 100644
--- a/drivers/media/platform/sunxi/sun4i-csi/sun4i_v4l2.c
+++ b/drivers/media/platform/sunxi/sun4i-csi/sun4i_v4l2.c
@@ -30,6 +30,28 @@ static const struct sun4i_csi_format sun4i_csi_formats[] = {
.hsub = 2,
.vsub = 2,
},
+ /* YUYV8 inputs */
+ {
+ .mbus = MEDIA_BUS_FMT_YUYV8_2X8,
+ .fourcc = V4L2_PIX_FMT_YUYV,
+ .input = CSI_INPUT_RAW,
+ .output = CSI_OUTPUT_RAW_PASSTHROUGH,
+ .num_planes = 1,
+ .bpp = { 16 },
+ .hsub = 1,
+ .vsub = 1,
+ },
+ /* UYVY8 inputs */
+ {
+ .mbus = MEDIA_BUS_FMT_UYVY8_2X8,
+ .fourcc = V4L2_PIX_FMT_UYVY,
+ .input = CSI_INPUT_RAW,
+ .output = CSI_OUTPUT_RAW_PASSTHROUGH,
+ .num_planes = 1,
+ .bpp = { 16 },
+ .hsub = 1,
+ .vsub = 1,
+ },
};
const struct sun4i_csi_format *sun4i_csi_find_format(const u32 *fourcc,
@@ -167,6 +189,88 @@ static int sun4i_csi_g_fmt_vid_cap(struct file *file, void *priv,
return 0;
}
+static void _sun4i_csi_try_fmt_packed(struct sun4i_csi *csi,
+ struct v4l2_pix_format *pix)
+{
+ const struct sun4i_csi_format *_fmt;
+ unsigned int height, width;
+
+ _fmt = sun4i_csi_find_format(&pix->pixelformat, NULL);
+ if (!_fmt)
+ _fmt = &sun4i_csi_formats[0];
+
+ pix->field = V4L2_FIELD_NONE;
+ pix->colorspace = V4L2_COLORSPACE_RAW;
+ pix->xfer_func = V4L2_YCBCR_ENC_DEFAULT;
+ pix->ycbcr_enc = V4L2_QUANTIZATION_DEFAULT;
+ pix->quantization = V4L2_XFER_FUNC_DEFAULT;
+ pix->pixelformat = _fmt->fourcc;
+
+ /* Align the width and height on the subsampling */
+ width = ALIGN(pix->width, _fmt->hsub);
+ height = ALIGN(pix->height, _fmt->vsub);
+
+ /* Clamp the width and height to our capabilities */
+ pix->width = clamp(width, _fmt->hsub, CSI_MAX_WIDTH);
+ pix->height = clamp(height, _fmt->vsub, CSI_MAX_HEIGHT);
+
+ pix->bytesperline = (pix->width * _fmt->bpp[0]) >> 3;
+ pix->sizeimage = pix->bytesperline * pix->height;
+}
+
+static int sun4i_csi_try_fmt_vid_cap_packed(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct sun4i_csi *csi = video_drvdata(file);
+
+ _sun4i_csi_try_fmt_packed(csi, &f->fmt.pix);
+
+ return 0;
+}
+
+static int sun4i_csi_s_fmt_vid_cap_packed(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct sun4i_csi *csi = video_drvdata(file);
+
+ _sun4i_csi_try_fmt_packed(csi, &f->fmt.pix);
+
+ csi->fmt.width = f->fmt.pix.width;
+ csi->fmt.height = f->fmt.pix.height;
+ csi->fmt.pixelformat = f->fmt.pix.pixelformat;
+ csi->fmt.field = f->fmt.pix.field;
+ csi->fmt.colorspace = f->fmt.pix.colorspace;
+ csi->fmt.flags = f->fmt.pix.flags;
+ csi->fmt.ycbcr_enc = f->fmt.pix.ycbcr_enc;
+ csi->fmt.quantization = f->fmt.pix.quantization;
+ csi->fmt.xfer_func = f->fmt.pix.xfer_func;
+ csi->fmt.num_planes = 1;
+ csi->fmt.plane_fmt[0].bytesperline = f->fmt.pix.bytesperline;
+ csi->fmt.plane_fmt[0].sizeimage = f->fmt.pix.sizeimage;
+
+ return 0;
+}
+
+static int sun4i_csi_g_fmt_vid_cap_packed(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct sun4i_csi *csi = video_drvdata(file);
+
+ f->fmt.pix_mp.width = csi->fmt.width;
+ f->fmt.pix.height = csi->fmt.height;
+ f->fmt.pix.pixelformat = csi->fmt.pixelformat;
+ f->fmt.pix.field = csi->fmt.field;
+ f->fmt.pix.colorspace = csi->fmt.colorspace;
+ f->fmt.pix.flags = csi->fmt.flags;
+ f->fmt.pix.ycbcr_enc = csi->fmt.ycbcr_enc;
+ f->fmt.pix.quantization = csi->fmt.quantization;
+ f->fmt.pix.xfer_func = csi->fmt.xfer_func;
+ f->fmt.pix.bytesperline = csi->fmt.plane_fmt[0].bytesperline;
+ f->fmt.pix.sizeimage = csi->fmt.plane_fmt[0].sizeimage;
+
+ return 0;
+}
+
static int sun4i_csi_enum_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
@@ -186,6 +290,10 @@ static const struct v4l2_ioctl_ops sun4i_csi_ioctl_ops = {
.vidioc_s_fmt_vid_cap_mplane = sun4i_csi_s_fmt_vid_cap,
.vidioc_try_fmt_vid_cap_mplane = sun4i_csi_try_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = sun4i_csi_g_fmt_vid_cap_packed,
+ .vidioc_s_fmt_vid_cap = sun4i_csi_s_fmt_vid_cap_packed,
+ .vidioc_try_fmt_vid_cap = sun4i_csi_try_fmt_vid_cap_packed,
+
.vidioc_enum_input = sun4i_csi_enum_input,
.vidioc_g_input = sun4i_csi_g_input,
.vidioc_s_input = sun4i_csi_s_input,
@@ -242,7 +350,7 @@ static int sun4i_csi_release(struct file *file)
mutex_lock(&csi->lock);
- v4l2_fh_release(file);
+ _vb2_fop_release(file, NULL);
v4l2_pipeline_pm_use(&csi->vdev.entity, 0);
pm_runtime_put(csi->dev);
@@ -356,7 +464,12 @@ int sun4i_csi_v4l2_register(struct sun4i_csi *csi)
struct video_device *vdev = &csi->vdev;
int ret;
- vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING;
+ if (!csi->packed) {
+ vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE;
+ } else {
+ vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE;
+ }
+ vdev->device_caps |= V4L2_CAP_STREAMING;
vdev->v4l2_dev = &csi->v4l;
vdev->queue = &csi->queue;
strscpy(vdev->name, KBUILD_MODNAME, sizeof(vdev->name));
--
2.17.1