215 lines
7.0 KiB
Diff
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
|
|
|