All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/4] R-Car VSP1 1-D Histogram support
@ 2016-08-17 12:20 Laurent Pinchart
  2016-08-17 12:20 ` [PATCH v2 1/4] v4l: Add metadata buffer type and format Laurent Pinchart
                   ` (5 more replies)
  0 siblings, 6 replies; 17+ messages in thread
From: Laurent Pinchart @ 2016-08-17 12:20 UTC (permalink / raw)
  To: linux-media
  Cc: linux-renesas-soc, Sakari Ailus, Hans Verkuil, Guennadi Liakhovetski

Hello,

This patch series implements support for the Renesas R-Car VSP1 1-D histogram
generator (HGO). It is based on top of the latest media tree's master branch,
and available for convenience at

        git://linuxtv.org/pinchartl/media.git vsp1/hgo

The series starts with the implementation and documentation of the new V4L2
metadata API (1/4), followed by a new pixel format for the R-Car VSP1 1-D
histogram (2/4). The last two patches (3/4 and 4/4) implement support for the
API in the vsp1 driver.

Laurent Pinchart (4):
  v4l: Add metadata buffer type and format
  v4l: Define a pixel format for the R-Car VSP1 1-D histogram engine
  v4l: vsp1: Add HGO support
  v4l: vsp1: Don't create HGO entity when the userspace API is disabled

 Documentation/media/uapi/v4l/buffer.rst            |   8 +
 Documentation/media/uapi/v4l/dev-meta.rst          |  69 +++
 Documentation/media/uapi/v4l/devices.rst           |   1 +
 Documentation/media/uapi/v4l/meta-formats.rst      |  15 +
 .../media/uapi/v4l/pixfmt-meta-vsp1-hgo.rst        | 170 +++++++
 Documentation/media/uapi/v4l/pixfmt.rst            |   1 +
 Documentation/media/uapi/v4l/vidioc-querycap.rst   |  14 +-
 Documentation/media/videodev2.h.rst.exceptions     |   2 +
 drivers/media/platform/Kconfig                     |   1 +
 drivers/media/platform/vsp1/Makefile               |   1 +
 drivers/media/platform/vsp1/vsp1.h                 |   3 +
 drivers/media/platform/vsp1/vsp1_drm.c             |   2 +-
 drivers/media/platform/vsp1/vsp1_drv.c             |  44 +-
 drivers/media/platform/vsp1/vsp1_entity.c          | 136 +++++-
 drivers/media/platform/vsp1/vsp1_entity.h          |   7 +-
 drivers/media/platform/vsp1/vsp1_hgo.c             | 501 +++++++++++++++++++++
 drivers/media/platform/vsp1/vsp1_hgo.h             |  50 ++
 drivers/media/platform/vsp1/vsp1_histo.c           | 324 +++++++++++++
 drivers/media/platform/vsp1/vsp1_histo.h           |  69 +++
 drivers/media/platform/vsp1/vsp1_pipe.c            |  22 +-
 drivers/media/platform/vsp1/vsp1_pipe.h            |   2 +
 drivers/media/platform/vsp1/vsp1_regs.h            |  24 +-
 drivers/media/platform/vsp1/vsp1_video.c           |  22 +-
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c      |  19 +
 drivers/media/v4l2-core/v4l2-dev.c                 |  16 +-
 drivers/media/v4l2-core/v4l2-ioctl.c               |  42 ++
 drivers/media/v4l2-core/videobuf2-v4l2.c           |   3 +
 include/media/v4l2-ioctl.h                         |  17 +
 include/uapi/linux/videodev2.h                     |  17 +
 29 files changed, 1552 insertions(+), 50 deletions(-)
 create mode 100644 Documentation/media/uapi/v4l/dev-meta.rst
 create mode 100644 Documentation/media/uapi/v4l/meta-formats.rst
 create mode 100644 Documentation/media/uapi/v4l/pixfmt-meta-vsp1-hgo.rst
 create mode 100644 drivers/media/platform/vsp1/vsp1_hgo.c
 create mode 100644 drivers/media/platform/vsp1/vsp1_hgo.h
 create mode 100644 drivers/media/platform/vsp1/vsp1_histo.c
 create mode 100644 drivers/media/platform/vsp1/vsp1_histo.h

-- 
Regards,

Laurent Pinchart


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v2 1/4] v4l: Add metadata buffer type and format
  2016-08-17 12:20 [PATCH v2 0/4] R-Car VSP1 1-D Histogram support Laurent Pinchart
@ 2016-08-17 12:20 ` Laurent Pinchart
  2016-08-29  9:13   ` Sakari Ailus
  2016-08-17 12:20 ` [PATCH v2 2/4] v4l: Define a pixel format for the R-Car VSP1 1-D histogram engine Laurent Pinchart
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 17+ messages in thread
From: Laurent Pinchart @ 2016-08-17 12:20 UTC (permalink / raw)
  To: linux-media
  Cc: linux-renesas-soc, Sakari Ailus, Hans Verkuil, Guennadi Liakhovetski

The metadata buffer type is used to transfer metadata between userspace
and kernelspace through a V4L2 buffers queue. It comes with a new
metadata capture capability and format description.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Guennadi Liakhovetski <guennadi.liakhovetski@intel.com>
---
Changes since v1:

- Rebased on top of the DocBook to reST conversion

 Documentation/media/uapi/v4l/buffer.rst          |  8 +++
 Documentation/media/uapi/v4l/dev-meta.rst        | 69 ++++++++++++++++++++++++
 Documentation/media/uapi/v4l/devices.rst         |  1 +
 Documentation/media/uapi/v4l/vidioc-querycap.rst | 14 +++--
 Documentation/media/videodev2.h.rst.exceptions   |  2 +
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c    | 19 +++++++
 drivers/media/v4l2-core/v4l2-dev.c               | 16 +++---
 drivers/media/v4l2-core/v4l2-ioctl.c             | 41 ++++++++++++++
 drivers/media/v4l2-core/videobuf2-v4l2.c         |  3 ++
 include/media/v4l2-ioctl.h                       | 17 ++++++
 include/uapi/linux/videodev2.h                   | 14 +++++
 11 files changed, 195 insertions(+), 9 deletions(-)
 create mode 100644 Documentation/media/uapi/v4l/dev-meta.rst

diff --git a/Documentation/media/uapi/v4l/buffer.rst b/Documentation/media/uapi/v4l/buffer.rst
index 5deb4a46f992..b5177cc63b86 100644
--- a/Documentation/media/uapi/v4l/buffer.rst
+++ b/Documentation/media/uapi/v4l/buffer.rst
@@ -499,6 +499,14 @@ enum v4l2_buf_type
        -  Buffer for Software Defined Radio (SDR) output stream, see
 	  :ref:`sdr`.
 
+    -  .. row 13
+
+       -  ``V4L2_BUF_TYPE_META_CAPTURE``
+
+       -  13
+
+       -  Buffer for metadata capture, see :ref:`metadata`.
+
 
 
 .. _buffer-flags:
diff --git a/Documentation/media/uapi/v4l/dev-meta.rst b/Documentation/media/uapi/v4l/dev-meta.rst
new file mode 100644
index 000000000000..252ed05b4841
--- /dev/null
+++ b/Documentation/media/uapi/v4l/dev-meta.rst
@@ -0,0 +1,69 @@
+.. -*- coding: utf-8; mode: rst -*-
+
+.. _metadata:
+
+******************
+Metadata Interface
+******************
+
+Metadata refers to any non-image data that supplements video frames with
+additional information. This may include statistics computed over the image
+or frame capture parameters supplied by the image source. This interface is
+intended for transfer of metadata to userspace and control of that operation.
+
+The metadata interface is implemented on video capture device nodes. The device
+can be dedicated to metadata or can implement both video and metadata capture
+as specified in its reported capabilities.
+
+.. note::
+
+    This is an :ref:`experimental` interface and may
+    change in the future.
+
+Querying Capabilities
+=====================
+
+Device nodes supporting the metadata interface set the ``V4L2_CAP_META_CAPTURE``
+flag in the ``device_caps`` field of the
+:ref:`v4l2_capability <v4l2-capability>` structure returned by the
+:ref:`VIDIOC_QUERYCAP` ioctl. That flag means the device can capture
+metadata to memory.
+
+At least one of the read/write or streaming I/O methods must be supported.
+
+
+Data Format Negotiation
+=======================
+
+The metadata device uses the :ref:`format` ioctls to select the capture format.
+The metadata buffer content format is bound to that selected format. In addition
+to the basic :ref:`format` ioctls, the :ref:`VIDIOC_ENUM_FMT` ioctl must be
+supported as well.
+
+To use the :ref:`format` ioctls applications set the ``type`` of the
+:ref:`v4l2_format <v4l2-format>` structure to ``V4L2_BUF_TYPE_META_CAPTURE``
+and use the :ref:`v4l2_meta_format <v4l2-meta-format>` ``meta`` member of the
+``fmt`` union as needed per the desired operation. The :ref:`v4l2-meta-format`
+structure contains two fields, ``dataformat`` is set by applications to the V4L2
+FourCC code of the desired format, and ``buffersize`` set by drivers to the
+maximum buffer size (in bytes) required for data transfer.
+
+.. _v4l2-meta-format:
+.. flat-table:: struct v4l2_meta_format
+    :header-rows:  0
+    :stub-columns: 0
+    :widths:       1 1 2
+
+    * - __u32
+      - ``dataformat``
+      - The data format, set by the application. This is a little endian
+        :ref:`four character code <v4l2-fourcc>`. V4L2 defines metadata formats
+        in :ref:`meta-formats`.
+    * - __u32
+      - ``buffersize``
+      - Maximum buffer size in bytes required for data. The value is set by the
+        driver.
+    * - __u8
+      - ``reserved[24]``
+      - This array is reserved for future extensions. Drivers and applications
+        must set it to zero.
diff --git a/Documentation/media/uapi/v4l/devices.rst b/Documentation/media/uapi/v4l/devices.rst
index aed0ce11d1f8..961e7fb62063 100644
--- a/Documentation/media/uapi/v4l/devices.rst
+++ b/Documentation/media/uapi/v4l/devices.rst
@@ -24,3 +24,4 @@ Interfaces
     dev-sdr
     dev-event
     dev-subdev
+    dev-meta
diff --git a/Documentation/media/uapi/v4l/vidioc-querycap.rst b/Documentation/media/uapi/v4l/vidioc-querycap.rst
index b10fed313f99..734fae6fc5e4 100644
--- a/Documentation/media/uapi/v4l/vidioc-querycap.rst
+++ b/Documentation/media/uapi/v4l/vidioc-querycap.rst
@@ -387,6 +387,14 @@ specification the ioctl returns an ``EINVAL`` error code.
 
     -  .. row 23
 
+       -  ``V4L2_CAP_META_CAPTURE``
+
+       -  0x00800000
+
+       -  The device supports the :ref:`metadata` capture interface.
+
+    -  .. row 24
+
        -  ``V4L2_CAP_READWRITE``
 
        -  0x01000000
@@ -394,7 +402,7 @@ specification the ioctl returns an ``EINVAL`` error code.
        -  The device supports the :ref:`read() <rw>` and/or
 	  :ref:`write() <rw>` I/O methods.
 
-    -  .. row 24
+    -  .. row 25
 
        -  ``V4L2_CAP_ASYNCIO``
 
@@ -402,7 +410,7 @@ specification the ioctl returns an ``EINVAL`` error code.
 
        -  The device supports the :ref:`asynchronous <async>` I/O methods.
 
-    -  .. row 25
+    -  .. row 26
 
        -  ``V4L2_CAP_STREAMING``
 
@@ -410,7 +418,7 @@ specification the ioctl returns an ``EINVAL`` error code.
 
        -  The device supports the :ref:`streaming <mmap>` I/O method.
 
-    -  .. row 26
+    -  .. row 27
 
        -  ``V4L2_CAP_DEVICE_CAPS``
 
diff --git a/Documentation/media/videodev2.h.rst.exceptions b/Documentation/media/videodev2.h.rst.exceptions
index 9bb9a6cc39d8..d1275725d367 100644
--- a/Documentation/media/videodev2.h.rst.exceptions
+++ b/Documentation/media/videodev2.h.rst.exceptions
@@ -27,6 +27,7 @@ replace symbol V4L2_FIELD_SEQ_TB v4l2-field
 replace symbol V4L2_FIELD_TOP v4l2-field
 
 # Documented enum v4l2_buf_type
+replace symbol V4L2_BUF_TYPE_META_CAPTURE v4l2-buf-type
 replace symbol V4L2_BUF_TYPE_SDR_CAPTURE v4l2-buf-type
 replace symbol V4L2_BUF_TYPE_SDR_OUTPUT v4l2-buf-type
 replace symbol V4L2_BUF_TYPE_SLICED_VBI_CAPTURE v4l2-buf-type
@@ -148,6 +149,7 @@ replace define V4L2_CAP_MODULATOR device-capabilities
 replace define V4L2_CAP_SDR_CAPTURE device-capabilities
 replace define V4L2_CAP_EXT_PIX_FORMAT device-capabilities
 replace define V4L2_CAP_SDR_OUTPUT device-capabilities
+replace define V4L2_CAP_META_CAPTURE device-capabilities
 replace define V4L2_CAP_READWRITE device-capabilities
 replace define V4L2_CAP_ASYNCIO device-capabilities
 replace define V4L2_CAP_STREAMING device-capabilities
diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index bacecbd68a6d..da2d836e8887 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -161,6 +161,20 @@ static inline int put_v4l2_sdr_format(struct v4l2_sdr_format *kp, struct v4l2_sd
 	return 0;
 }
 
+static inline int get_v4l2_meta_format(struct v4l2_meta_format *kp, struct v4l2_meta_format __user *up)
+{
+	if (copy_from_user(kp, up, sizeof(struct v4l2_meta_format)))
+		return -EFAULT;
+	return 0;
+}
+
+static inline int put_v4l2_meta_format(struct v4l2_meta_format *kp, struct v4l2_meta_format __user *up)
+{
+	if (copy_to_user(up, kp, sizeof(struct v4l2_meta_format)))
+		return -EFAULT;
+	return 0;
+}
+
 struct v4l2_format32 {
 	__u32	type;	/* enum v4l2_buf_type */
 	union {
@@ -170,6 +184,7 @@ struct v4l2_format32 {
 		struct v4l2_vbi_format	vbi;
 		struct v4l2_sliced_vbi_format	sliced;
 		struct v4l2_sdr_format	sdr;
+		struct v4l2_meta_format	meta;
 		__u8	raw_data[200];        /* user-defined */
 	} fmt;
 };
@@ -216,6 +231,8 @@ static int __get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __us
 	case V4L2_BUF_TYPE_SDR_CAPTURE:
 	case V4L2_BUF_TYPE_SDR_OUTPUT:
 		return get_v4l2_sdr_format(&kp->fmt.sdr, &up->fmt.sdr);
+	case V4L2_BUF_TYPE_META_CAPTURE:
+		return get_v4l2_meta_format(&kp->fmt.meta, &up->fmt.meta);
 	default:
 		pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
 								kp->type);
@@ -263,6 +280,8 @@ static int __put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __us
 	case V4L2_BUF_TYPE_SDR_CAPTURE:
 	case V4L2_BUF_TYPE_SDR_OUTPUT:
 		return put_v4l2_sdr_format(&kp->fmt.sdr, &up->fmt.sdr);
+	case V4L2_BUF_TYPE_META_CAPTURE:
+		return put_v4l2_meta_format(&kp->fmt.meta, &up->fmt.meta);
 	default:
 		pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
 								kp->type);
diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
index e6da353b39bc..70af31210cd3 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -574,30 +574,34 @@ static void determine_valid_ioctls(struct video_device *vdev)
 		set_bit(_IOC_NR(VIDIOC_ENUM_FREQ_BANDS), valid_ioctls);
 
 	if (is_vid) {
-		/* video specific ioctls */
+		/* video and metadata specific ioctls */
 		if ((is_rx && (ops->vidioc_enum_fmt_vid_cap ||
 			       ops->vidioc_enum_fmt_vid_cap_mplane ||
-			       ops->vidioc_enum_fmt_vid_overlay)) ||
+			       ops->vidioc_enum_fmt_vid_overlay ||
+			       ops->vidioc_enum_fmt_meta_cap)) ||
 		    (is_tx && (ops->vidioc_enum_fmt_vid_out ||
 			       ops->vidioc_enum_fmt_vid_out_mplane)))
 			set_bit(_IOC_NR(VIDIOC_ENUM_FMT), valid_ioctls);
 		if ((is_rx && (ops->vidioc_g_fmt_vid_cap ||
 			       ops->vidioc_g_fmt_vid_cap_mplane ||
-			       ops->vidioc_g_fmt_vid_overlay)) ||
+			       ops->vidioc_g_fmt_vid_overlay ||
+			       ops->vidioc_g_fmt_meta_cap)) ||
 		    (is_tx && (ops->vidioc_g_fmt_vid_out ||
 			       ops->vidioc_g_fmt_vid_out_mplane ||
 			       ops->vidioc_g_fmt_vid_out_overlay)))
 			 set_bit(_IOC_NR(VIDIOC_G_FMT), valid_ioctls);
 		if ((is_rx && (ops->vidioc_s_fmt_vid_cap ||
 			       ops->vidioc_s_fmt_vid_cap_mplane ||
-			       ops->vidioc_s_fmt_vid_overlay)) ||
+			       ops->vidioc_s_fmt_vid_overlay ||
+			       ops->vidioc_s_fmt_meta_cap)) ||
 		    (is_tx && (ops->vidioc_s_fmt_vid_out ||
 			       ops->vidioc_s_fmt_vid_out_mplane ||
 			       ops->vidioc_s_fmt_vid_out_overlay)))
 			 set_bit(_IOC_NR(VIDIOC_S_FMT), valid_ioctls);
 		if ((is_rx && (ops->vidioc_try_fmt_vid_cap ||
 			       ops->vidioc_try_fmt_vid_cap_mplane ||
-			       ops->vidioc_try_fmt_vid_overlay)) ||
+			       ops->vidioc_try_fmt_vid_overlay ||
+			       ops->vidioc_try_fmt_meta_cap)) ||
 		    (is_tx && (ops->vidioc_try_fmt_vid_out ||
 			       ops->vidioc_try_fmt_vid_out_mplane ||
 			       ops->vidioc_try_fmt_vid_out_overlay)))
@@ -663,7 +667,7 @@ static void determine_valid_ioctls(struct video_device *vdev)
 	}
 
 	if (is_vid || is_vbi || is_sdr) {
-		/* ioctls valid for video, vbi or sdr */
+		/* ioctls valid for video, metadata, vbi or sdr */
 		SET_VALID_IOCTL(ops, VIDIOC_REQBUFS, vidioc_reqbufs);
 		SET_VALID_IOCTL(ops, VIDIOC_QUERYBUF, vidioc_querybuf);
 		SET_VALID_IOCTL(ops, VIDIOC_QBUF, vidioc_qbuf);
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index 51a0fa144392..0afa07bfea35 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -37,6 +37,13 @@
 	memset((u8 *)(p) + offsetof(typeof(*(p)), field) + sizeof((p)->field), \
 	0, sizeof(*(p)) - offsetof(typeof(*(p)), field) - sizeof((p)->field))
 
+/* Zero out the end of the struct pointed to by p.  Everything including and
+ * after thee specified field is cleared.
+ */
+#define CLEAR_FROM_FIELD(p, field) \
+	memset((u8 *)(p) + offsetof(typeof(*(p)), field), \
+	0, sizeof(*(p)) - offsetof(typeof(*(p)), field))
+
 #define is_valid_ioctl(vfd, cmd) test_bit(_IOC_NR(cmd), (vfd)->valid_ioctls)
 
 struct std_descr {
@@ -155,6 +162,7 @@ const char *v4l2_type_names[] = {
 	[V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE] = "vid-out-mplane",
 	[V4L2_BUF_TYPE_SDR_CAPTURE]        = "sdr-cap",
 	[V4L2_BUF_TYPE_SDR_OUTPUT]         = "sdr-out",
+	[V4L2_BUF_TYPE_META_CAPTURE]       = "meta-cap",
 };
 EXPORT_SYMBOL(v4l2_type_names);
 
@@ -249,6 +257,7 @@ static void v4l_print_format(const void *arg, bool write_only)
 	const struct v4l2_sliced_vbi_format *sliced;
 	const struct v4l2_window *win;
 	const struct v4l2_sdr_format *sdr;
+	const struct v4l2_meta_format *meta;
 	unsigned i;
 
 	pr_cont("type=%s", prt_names(p->type, v4l2_type_names));
@@ -336,6 +345,15 @@ static void v4l_print_format(const void *arg, bool write_only)
 			(sdr->pixelformat >> 16) & 0xff,
 			(sdr->pixelformat >> 24) & 0xff);
 		break;
+	case V4L2_BUF_TYPE_META_CAPTURE:
+		meta = &p->fmt.meta;
+		pr_cont(", dataformat=%c%c%c%c, buffersize=%u\n",
+			(meta->dataformat >>  0) & 0xff,
+			(meta->dataformat >>  8) & 0xff,
+			(meta->dataformat >> 16) & 0xff,
+			(meta->dataformat >> 24) & 0xff,
+			meta->buffersize);
+		break;
 	}
 }
 
@@ -981,6 +999,10 @@ static int check_fmt(struct file *file, enum v4l2_buf_type type)
 		if (is_sdr && is_tx && ops->vidioc_g_fmt_sdr_out)
 			return 0;
 		break;
+	case V4L2_BUF_TYPE_META_CAPTURE:
+		if (is_vid && is_rx && ops->vidioc_g_fmt_meta_cap)
+			return 0;
+		break;
 	default:
 		break;
 	}
@@ -1349,6 +1371,11 @@ static int v4l_enum_fmt(const struct v4l2_ioctl_ops *ops,
 			break;
 		ret = ops->vidioc_enum_fmt_sdr_out(file, fh, arg);
 		break;
+	case V4L2_BUF_TYPE_META_CAPTURE:
+		if (unlikely(!is_rx || !is_vid || !ops->vidioc_enum_fmt_meta_cap))
+			break;
+		ret = ops->vidioc_enum_fmt_meta_cap(file, fh, arg);
+		break;
 	}
 	if (ret == 0)
 		v4l_fill_fmtdesc(p);
@@ -1447,6 +1474,10 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops,
 		if (unlikely(!is_tx || !is_sdr || !ops->vidioc_g_fmt_sdr_out))
 			break;
 		return ops->vidioc_g_fmt_sdr_out(file, fh, arg);
+	case V4L2_BUF_TYPE_META_CAPTURE:
+		if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_meta_cap))
+			break;
+		return ops->vidioc_g_fmt_meta_cap(file, fh, arg);
 	}
 	return -EINVAL;
 }
@@ -1534,6 +1565,11 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,
 			break;
 		CLEAR_AFTER_FIELD(p, fmt.sdr);
 		return ops->vidioc_s_fmt_sdr_out(file, fh, arg);
+	case V4L2_BUF_TYPE_META_CAPTURE:
+		if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_meta_cap))
+			break;
+		CLEAR_FROM_FIELD(p, fmt.meta.reserved);
+		return ops->vidioc_s_fmt_meta_cap(file, fh, arg);
 	}
 	return -EINVAL;
 }
@@ -1618,6 +1654,11 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops,
 			break;
 		CLEAR_AFTER_FIELD(p, fmt.sdr);
 		return ops->vidioc_try_fmt_sdr_out(file, fh, arg);
+	case V4L2_BUF_TYPE_META_CAPTURE:
+		if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_meta_cap))
+			break;
+		CLEAR_FROM_FIELD(p, fmt.meta.reserved);
+		return ops->vidioc_try_fmt_meta_cap(file, fh, arg);
 	}
 	return -EINVAL;
 }
diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c
index 9cfbb6e4bc28..7216668d1056 100644
--- a/drivers/media/v4l2-core/videobuf2-v4l2.c
+++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
@@ -575,6 +575,9 @@ int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
 	case V4L2_BUF_TYPE_SDR_OUTPUT:
 		requested_sizes[0] = f->fmt.sdr.buffersize;
 		break;
+	case V4L2_BUF_TYPE_META_CAPTURE:
+		requested_sizes[0] = f->fmt.meta.buffersize;
+		break;
 	default:
 		return -EINVAL;
 	}
diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
index 8b1d19bc9b0e..a32dcf78d4a3 100644
--- a/include/media/v4l2-ioctl.h
+++ b/include/media/v4l2-ioctl.h
@@ -43,6 +43,9 @@ struct v4l2_fh;
  * @vidioc_enum_fmt_sdr_out: pointer to the function that implements
  *	:ref:`VIDIOC_ENUM_FMT <vidioc_enum_fmt>` ioctl logic
  *	for Software Defined Radio output
+ * @vidioc_enum_fmt_meta_cap: pointer to the function that implements
+ *	:ref:`VIDIOC_ENUM_FMT <vidioc_enum_fmt>` ioctl logic
+ *	for metadata capture
  * @vidioc_g_fmt_vid_cap: pointer to the function that implements
  *	:ref:`VIDIOC_G_FMT <vidioc_g_fmt>` ioctl logic for video capture
  *	in single plane mode
@@ -73,6 +76,8 @@ struct v4l2_fh;
  * @vidioc_g_fmt_sdr_out: pointer to the function that implements
  *	:ref:`VIDIOC_G_FMT <vidioc_g_fmt>` ioctl logic for Software Defined
  *	Radio output
+ * @vidioc_g_fmt_meta_cap: pointer to the function that implements
+ *	:ref:`VIDIOC_G_FMT <vidioc_g_fmt>` ioctl logic for metadata capture
  * @vidioc_s_fmt_vid_cap: pointer to the function that implements
  *	:ref:`VIDIOC_S_FMT <vidioc_g_fmt>` ioctl logic for video capture
  *	in single plane mode
@@ -103,6 +108,8 @@ struct v4l2_fh;
  * @vidioc_s_fmt_sdr_out: pointer to the function that implements
  *	:ref:`VIDIOC_S_FMT <vidioc_g_fmt>` ioctl logic for Software Defined
  *	Radio output
+ * @vidioc_s_fmt_meta_cap: pointer to the function that implements
+ *	:ref:`VIDIOC_S_FMT <vidioc_g_fmt>` ioctl logic for metadata capture
  * @vidioc_try_fmt_vid_cap: pointer to the function that implements
  *	:ref:`VIDIOC_TRY_FMT <vidioc_g_fmt>` ioctl logic for video capture
  *	in single plane mode
@@ -135,6 +142,8 @@ struct v4l2_fh;
  * @vidioc_try_fmt_sdr_out: pointer to the function that implements
  *	:ref:`VIDIOC_TRY_FMT <vidioc_g_fmt>` ioctl logic for Software Defined
  *	Radio output
+ * @vidioc_try_fmt_meta_cap: pointer to the function that implements
+ *	:ref:`VIDIOC_TRY_FMT <vidioc_g_fmt>` ioctl logic for metadata capture
  * @vidioc_reqbufs: pointer to the function that implements
  *	:ref:`VIDIOC_REQBUFS <vidioc_reqbufs>` ioctl
  * @vidioc_querybuf: pointer to the function that implements
@@ -304,6 +313,8 @@ struct v4l2_ioctl_ops {
 					    struct v4l2_fmtdesc *f);
 	int (*vidioc_enum_fmt_sdr_out)     (struct file *file, void *fh,
 					    struct v4l2_fmtdesc *f);
+	int (*vidioc_enum_fmt_meta_cap)    (struct file *file, void *fh,
+					    struct v4l2_fmtdesc *f);
 
 	/* VIDIOC_G_FMT handlers */
 	int (*vidioc_g_fmt_vid_cap)    (struct file *file, void *fh,
@@ -330,6 +341,8 @@ struct v4l2_ioctl_ops {
 					struct v4l2_format *f);
 	int (*vidioc_g_fmt_sdr_out)    (struct file *file, void *fh,
 					struct v4l2_format *f);
+	int (*vidioc_g_fmt_meta_cap)   (struct file *file, void *fh,
+					struct v4l2_format *f);
 
 	/* VIDIOC_S_FMT handlers */
 	int (*vidioc_s_fmt_vid_cap)    (struct file *file, void *fh,
@@ -356,6 +369,8 @@ struct v4l2_ioctl_ops {
 					struct v4l2_format *f);
 	int (*vidioc_s_fmt_sdr_out)    (struct file *file, void *fh,
 					struct v4l2_format *f);
+	int (*vidioc_s_fmt_meta_cap)   (struct file *file, void *fh,
+					struct v4l2_format *f);
 
 	/* VIDIOC_TRY_FMT handlers */
 	int (*vidioc_try_fmt_vid_cap)    (struct file *file, void *fh,
@@ -382,6 +397,8 @@ struct v4l2_ioctl_ops {
 					  struct v4l2_format *f);
 	int (*vidioc_try_fmt_sdr_out)    (struct file *file, void *fh,
 					  struct v4l2_format *f);
+	int (*vidioc_try_fmt_meta_cap)   (struct file *file, void *fh,
+					  struct v4l2_format *f);
 
 	/* Buffer handlers */
 	int (*vidioc_reqbufs) (struct file *file, void *fh, struct v4l2_requestbuffers *b);
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 724f43e69d03..d1ac0250a966 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -143,6 +143,7 @@ enum v4l2_buf_type {
 	V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE  = 10,
 	V4L2_BUF_TYPE_SDR_CAPTURE          = 11,
 	V4L2_BUF_TYPE_SDR_OUTPUT           = 12,
+	V4L2_BUF_TYPE_META_CAPTURE         = 13,
 	/* Deprecated, do not use */
 	V4L2_BUF_TYPE_PRIVATE              = 0x80,
 };
@@ -435,6 +436,7 @@ struct v4l2_capability {
 #define V4L2_CAP_SDR_CAPTURE		0x00100000  /* Is a SDR capture device */
 #define V4L2_CAP_EXT_PIX_FORMAT		0x00200000  /* Supports the extended pixel format */
 #define V4L2_CAP_SDR_OUTPUT		0x00400000  /* Is a SDR output device */
+#define V4L2_CAP_META_CAPTURE		0x00800000  /* Is a metadata capture device */
 
 #define V4L2_CAP_READWRITE              0x01000000  /* read/write systemcalls */
 #define V4L2_CAP_ASYNCIO                0x02000000  /* async I/O */
@@ -2002,6 +2004,17 @@ struct v4l2_sdr_format {
 } __attribute__ ((packed));
 
 /**
+ * struct v4l2_meta_format - metadata format definition
+ * @dataformat:		little endian four character code (fourcc)
+ * @buffersize:		maximum size in bytes required for data
+ */
+struct v4l2_meta_format {
+	__u32				dataformat;
+	__u32				buffersize;
+	__u8				reserved[24];
+} __attribute__ ((packed));
+
+/**
  * struct v4l2_format - stream data format
  * @type:	enum v4l2_buf_type; type of the data stream
  * @pix:	definition of an image format
@@ -2020,6 +2033,7 @@ struct v4l2_format {
 		struct v4l2_vbi_format		vbi;     /* V4L2_BUF_TYPE_VBI_CAPTURE */
 		struct v4l2_sliced_vbi_format	sliced;  /* V4L2_BUF_TYPE_SLICED_VBI_CAPTURE */
 		struct v4l2_sdr_format		sdr;     /* V4L2_BUF_TYPE_SDR_CAPTURE */
+		struct v4l2_meta_format		meta;    /* V4L2_BUF_TYPE_META_CAPTURE */
 		__u8	raw_data[200];                   /* user-defined */
 	} fmt;
 };
-- 
Regards,

Laurent Pinchart


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 2/4] v4l: Define a pixel format for the R-Car VSP1 1-D histogram engine
  2016-08-17 12:20 [PATCH v2 0/4] R-Car VSP1 1-D Histogram support Laurent Pinchart
  2016-08-17 12:20 ` [PATCH v2 1/4] v4l: Add metadata buffer type and format Laurent Pinchart
@ 2016-08-17 12:20 ` Laurent Pinchart
  2016-09-06 17:06   ` Mauro Carvalho Chehab
  2016-08-17 12:20 ` [PATCH v2 3/4] v4l: vsp1: Add HGO support Laurent Pinchart
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 17+ messages in thread
From: Laurent Pinchart @ 2016-08-17 12:20 UTC (permalink / raw)
  To: linux-media
  Cc: linux-renesas-soc, Sakari Ailus, Hans Verkuil, Guennadi Liakhovetski

The format is used on the R-Car VSP1 video queues that carry
1-D histogram statistics data.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
Changes since v1:

- Rebased on top of the DocBook to reST conversion

 Documentation/media/uapi/v4l/meta-formats.rst      |  15 ++
 .../media/uapi/v4l/pixfmt-meta-vsp1-hgo.rst        | 170 +++++++++++++++++++++
 Documentation/media/uapi/v4l/pixfmt.rst            |   1 +
 drivers/media/v4l2-core/v4l2-ioctl.c               |   1 +
 include/uapi/linux/videodev2.h                     |   3 +
 5 files changed, 190 insertions(+)
 create mode 100644 Documentation/media/uapi/v4l/meta-formats.rst
 create mode 100644 Documentation/media/uapi/v4l/pixfmt-meta-vsp1-hgo.rst

diff --git a/Documentation/media/uapi/v4l/meta-formats.rst b/Documentation/media/uapi/v4l/meta-formats.rst
new file mode 100644
index 000000000000..05ab91e12f10
--- /dev/null
+++ b/Documentation/media/uapi/v4l/meta-formats.rst
@@ -0,0 +1,15 @@
+.. -*- coding: utf-8; mode: rst -*-
+
+.. _meta-formats:
+
+****************
+Metadata Formats
+****************
+
+These formats are used for the :ref:`metadata` interface only.
+
+
+.. toctree::
+    :maxdepth: 1
+
+    pixfmt-meta-vsp1-hgo
diff --git a/Documentation/media/uapi/v4l/pixfmt-meta-vsp1-hgo.rst b/Documentation/media/uapi/v4l/pixfmt-meta-vsp1-hgo.rst
new file mode 100644
index 000000000000..e935e4525b10
--- /dev/null
+++ b/Documentation/media/uapi/v4l/pixfmt-meta-vsp1-hgo.rst
@@ -0,0 +1,170 @@
+.. -*- coding: utf-8; mode: rst -*-
+
+.. _v4l2-meta-fmt-vsp1-hgo:
+
+*******************************
+V4L2_META_FMT_VSP1_HGO ('VSPH')
+*******************************
+
+*man V4L2_META_FMT_VSP1_HGO(2)*
+
+Renesas R-Car VSP1 1-D Histogram Data
+
+
+Description
+===========
+
+This format describes histogram data generated by the Renesas R-Car VSP1 1-D
+Histogram (HGO) engine.
+
+The VSP1 HGO is a histogram computation engine that can operate on RGB, YCrCb
+or HSV data. It operates on a possibly cropped and subsampled input image and
+computes the minimum, maximum and sum of all pixels as well as per-channel
+histograms.
+
+The HGO can compute histograms independently per channel, on the maximum of the
+three channels (RGB data only) or on the Y channel only (YCbCr only). It can
+additionally output the histogram with 64 or 256 bins, resulting in four
+possible modes of operation.
+
+- In *64 bins normal mode*, the HGO operates on the three channels independently
+  to compute three 64-bins histograms. RGB, YCbCr and HSV image formats are
+  supported.
+- In *64 bins maximum mode*, the HGO operates on the maximum of the (R, G, B)
+  channels to compute a single 64-bins histogram. Only the RGB image format is
+  supported.
+- In *256 bins normal mode*, the HGO operates on the Y channel to compute a
+  single 256-bins histogram. Only the YCbCr image format is supported.
+- In *256 bins maximum mode*, the HGO operates on the maximum of the (R, G, B)
+  channels to compute a single 256-bins histogram. Only the RGB image format is
+  supported.
+
+**Byte Order.**
+All data is stored in memory in little endian format. Each cell in the tables
+contains one byte.
+
+.. flat-table:: VSP1 HGO Data - 64 Bins, Normal Mode (792 bytes)
+    :header-rows:  2
+    :stub-columns: 0
+
+    * - Offset
+      - :cspan:`4` Memory
+    * -
+      - [31:24]
+      - [23:16]
+      - [15:8]
+      - [7:0]
+    * - 0
+      - -
+      - R/Cr/H max [7:0]
+      - -
+      - R/Cr/H min [7:0]
+    * - 4
+      - -
+      - G/Y/S max [7:0]
+      - -
+      - G/Y/S min [7:0]
+    * - 8
+      - -
+      - B/Cb/V max [7:0]
+      - -
+      - B/Cb/V min [7:0]
+    * - 12
+      - :cspan:`4` R/Cr/H sum [31:0]
+    * - 16
+      - :cspan:`4` G/Y/S sum [31:0]
+    * - 20
+      - :cspan:`4` B/Cb/V sum [31:0]
+    * - 24
+      - :cspan:`4` R/Cr/H bin 0 [31:0]
+    * -
+      - :cspan:`4` ...
+    * - 276
+      - :cspan:`4` R/Cr/H bin 63 [31:0]
+    * - 280
+      - :cspan:`4` G/Y/S bin 0 [31:0]
+    * -
+      - :cspan:`4` ...
+    * - 532
+      - :cspan:`4` G/Y/S bin 63 [31:0]
+    * - 536
+      - :cspan:`4` B/Cb/V bin 0 [31:0]
+    * -
+      - :cspan:`4` ...
+    * - 788
+      - :cspan:`4` B/Cb/V bin 63 [31:0]
+
+.. flat-table:: VSP1 HGO Data - 64 Bins, Max Mode (264 bytes)
+    :header-rows:  2
+    :stub-columns: 0
+
+    * - Offset
+      - :cspan:`4` Memory
+    * -
+      - [31:24]
+      - [23:16]
+      - [15:8]
+      - [7:0]
+    * - 0
+      - -
+      - max(R,G,B) max [7:0]
+      - -
+      - max(R,G,B) min [7:0]
+    * - 4
+      - :cspan:`4` max(R,G,B) sum [31:0]
+    * - 8
+      - :cspan:`4` max(R,G,B) bin 0 [31:0]
+    * -
+      - :cspan:`4` ...
+    * - 260
+      - :cspan:`4` max(R,G,B) bin 63 [31:0]
+
+.. flat-table:: VSP1 HGO Data - 256 Bins, Normal Mode (1032 bytes)
+    :header-rows:  2
+    :stub-columns: 0
+
+    * - Offset
+      - :cspan:`4` Memory
+    * -
+      - [31:24]
+      - [23:16]
+      - [15:8]
+      - [7:0]
+    * - 0
+      - -
+      - Y max [7:0]
+      - -
+      - Y min [7:0]
+    * - 4
+      - :cspan:`4` Y sum [31:0]
+    * - 8
+      - :cspan:`4` Y bin 0 [31:0]
+    * -
+      - :cspan:`4` ...
+    * - 1028
+      - :cspan:`4` Y bin 255 [31:0]
+
+.. flat-table:: VSP1 HGO Data - 256 Bins, Max Mode (1032 bytes)
+    :header-rows:  2
+    :stub-columns: 0
+
+    * - Offset
+      - :cspan:`4` Memory
+    * -
+      - [31:24]
+      - [23:16]
+      - [15:8]
+      - [7:0]
+    * - 0
+      - -
+      - max(R,G,B) max [7:0]
+      - -
+      - max(R,G,B) min [7:0]
+    * - 4
+      - :cspan:`4` max(R,G,B) sum [31:0]
+    * - 8
+      - :cspan:`4` max(R,G,B) bin 0 [31:0]
+    * -
+      - :cspan:`4` ...
+    * - 1028
+      - :cspan:`4` max(R,G,B) bin 255 [31:0]
diff --git a/Documentation/media/uapi/v4l/pixfmt.rst b/Documentation/media/uapi/v4l/pixfmt.rst
index 81222a99f7ce..e3738a2eb05f 100644
--- a/Documentation/media/uapi/v4l/pixfmt.rst
+++ b/Documentation/media/uapi/v4l/pixfmt.rst
@@ -32,4 +32,5 @@ see also :ref:`VIDIOC_G_FBUF <VIDIOC_G_FBUF>`.)
     depth-formats
     pixfmt-013
     sdr-formats
+    meta-formats
     pixfmt-reserved
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index 0afa07bfea35..8425f0b8ebfb 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -1265,6 +1265,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
 	case V4L2_SDR_FMT_CS8:		descr = "Complex S8"; break;
 	case V4L2_SDR_FMT_CS14LE:	descr = "Complex S14LE"; break;
 	case V4L2_SDR_FMT_RU12LE:	descr = "Real U12LE"; break;
+	case V4L2_META_FMT_VSP1_HGO:	descr = "R-Car VSP1 1-D Histogram"; break;
 
 	default:
 		/* Compressed formats */
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index d1ac0250a966..05b97c2067d4 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -637,6 +637,9 @@ struct v4l2_pix_format {
 #define V4L2_SDR_FMT_CS14LE       v4l2_fourcc('C', 'S', '1', '4') /* complex s14le */
 #define V4L2_SDR_FMT_RU12LE       v4l2_fourcc('R', 'U', '1', '2') /* real u12le */
 
+/* Meta-data formats */
+#define V4L2_META_FMT_VSP1_HGO    v4l2_fourcc('V', 'S', 'P', 'H') /* R-Car VSP1 Histogram */
+
 /* priv field value to indicates that subsequent fields are valid. */
 #define V4L2_PIX_FMT_PRIV_MAGIC		0xfeedcafe
 
-- 
Regards,

Laurent Pinchart


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 3/4] v4l: vsp1: Add HGO support
  2016-08-17 12:20 [PATCH v2 0/4] R-Car VSP1 1-D Histogram support Laurent Pinchart
  2016-08-17 12:20 ` [PATCH v2 1/4] v4l: Add metadata buffer type and format Laurent Pinchart
  2016-08-17 12:20 ` [PATCH v2 2/4] v4l: Define a pixel format for the R-Car VSP1 1-D histogram engine Laurent Pinchart
@ 2016-08-17 12:20 ` Laurent Pinchart
  2016-08-17 12:20 ` [PATCH v2 4/4] v4l: vsp1: Don't create HGO entity when the userspace API is disabled Laurent Pinchart
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 17+ messages in thread
From: Laurent Pinchart @ 2016-08-17 12:20 UTC (permalink / raw)
  To: linux-media
  Cc: linux-renesas-soc, Sakari Ailus, Hans Verkuil, Guennadi Liakhovetski

The HGO is a Histogram Generator One-Dimension. It computes per-channel
histograms over a configurable region of the image with optional
subsampling.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
Changes since v1:

- Added VIDIOC_ENUM_FMT support in the vsp1 driver
- Made the pixel format configurable in the vsp1_histo API

 drivers/media/platform/Kconfig            |   1 +
 drivers/media/platform/vsp1/Makefile      |   1 +
 drivers/media/platform/vsp1/vsp1.h        |   3 +
 drivers/media/platform/vsp1/vsp1_drm.c    |   2 +-
 drivers/media/platform/vsp1/vsp1_drv.c    |  44 ++-
 drivers/media/platform/vsp1/vsp1_entity.c | 136 +++++++-
 drivers/media/platform/vsp1/vsp1_entity.h |   7 +-
 drivers/media/platform/vsp1/vsp1_hgo.c    | 501 ++++++++++++++++++++++++++++++
 drivers/media/platform/vsp1/vsp1_hgo.h    |  50 +++
 drivers/media/platform/vsp1/vsp1_histo.c  | 324 +++++++++++++++++++
 drivers/media/platform/vsp1/vsp1_histo.h  |  69 ++++
 drivers/media/platform/vsp1/vsp1_pipe.c   |  22 +-
 drivers/media/platform/vsp1/vsp1_pipe.h   |   2 +
 drivers/media/platform/vsp1/vsp1_regs.h   |  24 +-
 drivers/media/platform/vsp1/vsp1_video.c  |  22 +-
 15 files changed, 1167 insertions(+), 41 deletions(-)
 create mode 100644 drivers/media/platform/vsp1/vsp1_hgo.c
 create mode 100644 drivers/media/platform/vsp1/vsp1_hgo.h
 create mode 100644 drivers/media/platform/vsp1/vsp1_histo.c
 create mode 100644 drivers/media/platform/vsp1/vsp1_histo.h

diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index f25344bc7912..d3ba94f3913d 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -297,6 +297,7 @@ config VIDEO_RENESAS_VSP1
 	depends on (ARCH_RENESAS && OF) || COMPILE_TEST
 	depends on (!ARM64 && !VIDEO_RENESAS_FCP) || VIDEO_RENESAS_FCP
 	select VIDEOBUF2_DMA_CONTIG
+	select VIDEOBUF2_VMALLOC
 	---help---
 	  This is a V4L2 driver for the Renesas VSP1 video processing engine.
 
diff --git a/drivers/media/platform/vsp1/Makefile b/drivers/media/platform/vsp1/Makefile
index 1328e1bd2143..8ab6a063569e 100644
--- a/drivers/media/platform/vsp1/Makefile
+++ b/drivers/media/platform/vsp1/Makefile
@@ -3,6 +3,7 @@ vsp1-y					+= vsp1_dl.o vsp1_drm.o vsp1_video.o
 vsp1-y					+= vsp1_rpf.o vsp1_rwpf.o vsp1_wpf.o
 vsp1-y					+= vsp1_clu.o vsp1_hsit.o vsp1_lut.o
 vsp1-y					+= vsp1_bru.o vsp1_sru.o vsp1_uds.o
+vsp1-y					+= vsp1_hgo.o vsp1_histo.o
 vsp1-y					+= vsp1_lif.o
 
 obj-$(CONFIG_VIDEO_RENESAS_VSP1)	+= vsp1.o
diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h
index 06a2ec7e5ad4..9dce3ea85252 100644
--- a/drivers/media/platform/vsp1/vsp1.h
+++ b/drivers/media/platform/vsp1/vsp1.h
@@ -32,6 +32,7 @@ struct vsp1_entity;
 struct vsp1_platform_data;
 struct vsp1_bru;
 struct vsp1_clu;
+struct vsp1_hgo;
 struct vsp1_hsit;
 struct vsp1_lif;
 struct vsp1_lut;
@@ -50,6 +51,7 @@ struct vsp1_uds;
 #define VSP1_HAS_CLU		(1 << 4)
 #define VSP1_HAS_WPF_VFLIP	(1 << 5)
 #define VSP1_HAS_WPF_HFLIP	(1 << 6)
+#define VSP1_HAS_HGO		(1 << 7)
 
 struct vsp1_device_info {
 	u32 version;
@@ -71,6 +73,7 @@ struct vsp1_device {
 
 	struct vsp1_bru *bru;
 	struct vsp1_clu *clu;
+	struct vsp1_hgo *hgo;
 	struct vsp1_hsit *hsi;
 	struct vsp1_hsit *hst;
 	struct vsp1_lif *lif;
diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index fe9665e57b3b..0a98a3c49b73 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -489,7 +489,7 @@ void vsp1_du_atomic_flush(struct device *dev)
 			}
 		}
 
-		vsp1_entity_route_setup(entity, pipe->dl);
+		vsp1_entity_route_setup(entity, pipe, pipe->dl);
 
 		if (entity->ops->configure) {
 			entity->ops->configure(entity, pipe, pipe->dl, true);
diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
index cc316d281687..327066c25144 100644
--- a/drivers/media/platform/vsp1/vsp1_drv.c
+++ b/drivers/media/platform/vsp1/vsp1_drv.c
@@ -30,6 +30,7 @@
 #include "vsp1_clu.h"
 #include "vsp1_dl.h"
 #include "vsp1_drm.h"
+#include "vsp1_hgo.h"
 #include "vsp1_hsit.h"
 #include "vsp1_lif.h"
 #include "vsp1_lut.h"
@@ -105,7 +106,8 @@ static int vsp1_create_sink_links(struct vsp1_device *vsp1,
 		if (source->type == sink->type)
 			continue;
 
-		if (source->type == VSP1_ENTITY_LIF ||
+		if (source->type == VSP1_ENTITY_HGO ||
+		    source->type == VSP1_ENTITY_LIF ||
 		    source->type == VSP1_ENTITY_WPF)
 			continue;
 
@@ -148,6 +150,16 @@ static int vsp1_uapi_create_links(struct vsp1_device *vsp1)
 			return ret;
 	}
 
+	if (vsp1->hgo) {
+		ret = media_create_pad_link(&vsp1->hgo->entity.subdev.entity,
+					    HGO_PAD_SOURCE,
+					    &vsp1->hgo->histo.video.entity, 0,
+					    MEDIA_LNK_FL_ENABLED |
+					    MEDIA_LNK_FL_IMMUTABLE);
+		if (ret < 0)
+			return ret;
+	}
+
 	if (vsp1->lif) {
 		ret = media_create_pad_link(&vsp1->wpf[0]->entity.subdev.entity,
 					    RWPF_PAD_SOURCE,
@@ -278,6 +290,16 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
 
 	list_add_tail(&vsp1->hst->entity.list_dev, &vsp1->entities);
 
+	if (vsp1->info->features & VSP1_HAS_HGO) {
+		vsp1->hgo = vsp1_hgo_create(vsp1);
+		if (IS_ERR(vsp1->hgo)) {
+			ret = PTR_ERR(vsp1->hgo);
+			goto done;
+		}
+
+		list_add_tail(&vsp1->hgo->entity.list_dev, &vsp1->entities);
+	}
+
 	/* The LIF is only supported when used in conjunction with the DU, in
 	 * which case the userspace API is disabled. If the userspace API is
 	 * enabled skip the LIF, even when present.
@@ -560,8 +582,8 @@ static const struct vsp1_device_info vsp1_device_infos[] = {
 	{
 		.version = VI6_IP_VERSION_MODEL_VSPS_H2,
 		.gen = 2,
-		.features = VSP1_HAS_BRU | VSP1_HAS_CLU | VSP1_HAS_LUT
-			  | VSP1_HAS_SRU | VSP1_HAS_WPF_VFLIP,
+		.features = VSP1_HAS_BRU | VSP1_HAS_CLU | VSP1_HAS_HGO
+			  | VSP1_HAS_LUT | VSP1_HAS_SRU | VSP1_HAS_WPF_VFLIP,
 		.rpf_count = 5,
 		.uds_count = 3,
 		.wpf_count = 4,
@@ -579,7 +601,8 @@ static const struct vsp1_device_info vsp1_device_infos[] = {
 	}, {
 		.version = VI6_IP_VERSION_MODEL_VSPD_GEN2,
 		.gen = 2,
-		.features = VSP1_HAS_BRU | VSP1_HAS_LIF | VSP1_HAS_LUT,
+		.features = VSP1_HAS_BRU | VSP1_HAS_HGO | VSP1_HAS_LIF
+			  | VSP1_HAS_LUT,
 		.rpf_count = 4,
 		.uds_count = 1,
 		.wpf_count = 1,
@@ -588,8 +611,8 @@ static const struct vsp1_device_info vsp1_device_infos[] = {
 	}, {
 		.version = VI6_IP_VERSION_MODEL_VSPS_M2,
 		.gen = 2,
-		.features = VSP1_HAS_BRU | VSP1_HAS_CLU | VSP1_HAS_LUT
-			  | VSP1_HAS_SRU | VSP1_HAS_WPF_VFLIP,
+		.features = VSP1_HAS_BRU | VSP1_HAS_CLU | VSP1_HAS_HGO
+			  | VSP1_HAS_LUT | VSP1_HAS_SRU | VSP1_HAS_WPF_VFLIP,
 		.rpf_count = 5,
 		.uds_count = 1,
 		.wpf_count = 4,
@@ -598,8 +621,9 @@ static const struct vsp1_device_info vsp1_device_infos[] = {
 	}, {
 		.version = VI6_IP_VERSION_MODEL_VSPI_GEN3,
 		.gen = 3,
-		.features = VSP1_HAS_CLU | VSP1_HAS_LUT | VSP1_HAS_SRU
-			  | VSP1_HAS_WPF_HFLIP | VSP1_HAS_WPF_VFLIP,
+		.features = VSP1_HAS_CLU | VSP1_HAS_HGO | VSP1_HAS_LUT
+			  | VSP1_HAS_SRU | VSP1_HAS_WPF_HFLIP
+			  | VSP1_HAS_WPF_VFLIP,
 		.rpf_count = 1,
 		.uds_count = 1,
 		.wpf_count = 1,
@@ -615,8 +639,8 @@ static const struct vsp1_device_info vsp1_device_infos[] = {
 	}, {
 		.version = VI6_IP_VERSION_MODEL_VSPBC_GEN3,
 		.gen = 3,
-		.features = VSP1_HAS_BRU | VSP1_HAS_CLU | VSP1_HAS_LUT
-			  | VSP1_HAS_WPF_VFLIP,
+		.features = VSP1_HAS_BRU | VSP1_HAS_CLU | VSP1_HAS_HGO
+			  | VSP1_HAS_LUT | VSP1_HAS_WPF_VFLIP,
 		.rpf_count = 5,
 		.wpf_count = 1,
 		.num_bru_inputs = 5,
diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c
index 4cf6cc719c00..a6b7d8755329 100644
--- a/drivers/media/platform/vsp1/vsp1_entity.c
+++ b/drivers/media/platform/vsp1/vsp1_entity.c
@@ -21,6 +21,8 @@
 #include "vsp1.h"
 #include "vsp1_dl.h"
 #include "vsp1_entity.h"
+#include "vsp1_pipe.h"
+#include "vsp1_rwpf.h"
 
 static inline struct vsp1_entity *
 media_entity_to_vsp1_entity(struct media_entity *entity)
@@ -28,11 +30,28 @@ media_entity_to_vsp1_entity(struct media_entity *entity)
 	return container_of(entity, struct vsp1_entity, subdev.entity);
 }
 
-void vsp1_entity_route_setup(struct vsp1_entity *source,
+void vsp1_entity_route_setup(struct vsp1_entity *entity,
+			     struct vsp1_pipeline *pipe,
 			     struct vsp1_dl_list *dl)
 {
+	struct vsp1_entity *source;
 	struct vsp1_entity *sink;
 
+	if (entity->type == VSP1_ENTITY_HGO) {
+		u32 smppt;
+
+		/* The HGO is a special case, its routing is configured on the
+		 * sink pad.
+		 */
+		source = media_entity_to_vsp1_entity(entity->sources[0]);
+		smppt = (pipe->output->entity.index << VI6_DPR_SMPPT_TGW_SHIFT)
+		      | (source->route->output << VI6_DPR_SMPPT_PT_SHIFT);
+
+		vsp1_dl_list_write(dl, VI6_DPR_HGO_SMPPT, smppt);
+		return;
+	}
+
+	source = entity;
 	if (source->route->reg == 0)
 		return;
 
@@ -267,25 +286,30 @@ int vsp1_subdev_enum_frame_size(struct v4l2_subdev *subdev,
  * Media Operations
  */
 
-int vsp1_entity_link_setup(struct media_entity *entity,
-			   const struct media_pad *local,
-			   const struct media_pad *remote, u32 flags)
+static int vsp1_entity_link_setup_source(const struct media_pad *source_pad,
+					 const struct media_pad *sink_pad,
+					 u32 flags)
 {
 	struct vsp1_entity *source;
 
-	if (!(local->flags & MEDIA_PAD_FL_SOURCE))
-		return 0;
-
-	source = media_entity_to_vsp1_entity(local->entity);
+	source = media_entity_to_vsp1_entity(source_pad->entity);
 
 	if (!source->route)
 		return 0;
 
 	if (flags & MEDIA_LNK_FL_ENABLED) {
-		if (source->sink)
-			return -EBUSY;
-		source->sink = remote->entity;
-		source->sink_pad = remote->index;
+		struct vsp1_entity *sink
+			= media_entity_to_vsp1_entity(sink_pad->entity);
+
+		/* Fan-out is limited to one for the normal data path plus an
+		 * optional HGO. We ignore the HGO here.
+		 */
+		if (sink->type != VSP1_ENTITY_HGO) {
+			if (source->sink)
+				return -EBUSY;
+			source->sink = sink_pad->entity;
+			source->sink_pad = sink_pad->index;
+		}
 	} else {
 		source->sink = NULL;
 		source->sink_pad = 0;
@@ -294,6 +318,84 @@ int vsp1_entity_link_setup(struct media_entity *entity,
 	return 0;
 }
 
+static int vsp1_entity_link_setup_sink(const struct media_pad *source_pad,
+				       const struct media_pad *sink_pad,
+				       u32 flags)
+{
+	struct vsp1_entity *sink;
+
+	sink = media_entity_to_vsp1_entity(sink_pad->entity);
+
+	if (flags & MEDIA_LNK_FL_ENABLED) {
+		/* Fan-in is limited to one. */
+		if (sink->sources[sink_pad->index])
+			return -EBUSY;
+
+		sink->sources[sink_pad->index] = source_pad->entity;
+	} else {
+		sink->sources[sink_pad->index] = NULL;
+	}
+
+	return 0;
+}
+
+int vsp1_entity_link_setup(struct media_entity *entity,
+			   const struct media_pad *local,
+			   const struct media_pad *remote, u32 flags)
+{
+	if (local->flags & MEDIA_PAD_FL_SOURCE)
+		return vsp1_entity_link_setup_source(local, remote, flags);
+	else
+		return vsp1_entity_link_setup_sink(remote, local, flags);
+}
+
+/**
+ * vsp1_entity_remote_pad - Find the pad at the remote end of a link
+ * @pad: Pad at the local end of the link
+ *
+ * Search for a remote pad connected to the given pad by iterating over all
+ * links originating or terminating at that pad until an enabled link is found.
+ *
+ * Our link setup implementation guarantees that the output fan-out will not be
+ * higher than one for the data pipelines, except for the link to the HGO that
+ * can be enabled in addition to a regular data link. When traversing outgoing
+ * links this function ignores HGO entities and should thus be used in place of
+ * the generic media_entity_remote_pad() function when traversing data
+ * pipelines.
+ *
+ * Return a pointer to the pad at the remote end of the first found enabled
+ * link, or NULL if no enabled link has been found.
+ */
+struct media_pad *vsp1_entity_remote_pad(struct media_pad *pad)
+{
+	struct media_link *link;
+
+	list_for_each_entry(link, &pad->entity->links, list) {
+		struct vsp1_entity *entity;
+
+		if (!(link->flags & MEDIA_LNK_FL_ENABLED))
+			continue;
+
+		/* If we're the sink the source will never be an HGO. */
+		if (link->sink == pad)
+			return link->source;
+
+		if (link->source != pad)
+			continue;
+
+		/* If the sink isn't a subdevice it can't be an HGO. */
+		if (!is_media_entity_v4l2_subdev(link->sink->entity))
+			return link->sink;
+
+		entity = media_entity_to_vsp1_entity(link->sink->entity);
+		if (entity->type != VSP1_ENTITY_HGO)
+			return link->sink;
+	}
+
+	return NULL;
+
+}
+
 /* -----------------------------------------------------------------------------
  * Initialization
  */
@@ -320,6 +422,7 @@ static const struct vsp1_route vsp1_routes[] = {
 	    VI6_DPR_NODE_BRU_IN(2), VI6_DPR_NODE_BRU_IN(3),
 	    VI6_DPR_NODE_BRU_IN(4) }, VI6_DPR_NODE_BRU_OUT },
 	VSP1_ENTITY_ROUTE(CLU),
+	{ VSP1_ENTITY_HGO, 0, 0, { 0, }, 0 },
 	VSP1_ENTITY_ROUTE(HSI),
 	VSP1_ENTITY_ROUTE(HST),
 	{ VSP1_ENTITY_LIF, 0, 0, { VI6_DPR_NODE_LIF, }, VI6_DPR_NODE_LIF },
@@ -370,7 +473,14 @@ int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity,
 	for (i = 0; i < num_pads - 1; ++i)
 		entity->pads[i].flags = MEDIA_PAD_FL_SINK;
 
-	entity->pads[num_pads - 1].flags = MEDIA_PAD_FL_SOURCE;
+	entity->sources = devm_kcalloc(vsp1->dev, max(num_pads - 1, 1U),
+				       sizeof(*entity->sources), GFP_KERNEL);
+	if (entity->sources == NULL)
+		return -ENOMEM;
+
+	/* Single-pad entities only have a sink. */
+	entity->pads[num_pads - 1].flags = num_pads > 1 ? MEDIA_PAD_FL_SOURCE
+					 : MEDIA_PAD_FL_SINK;
 
 	/* Initialize the media entity. */
 	ret = media_entity_pads_init(&entity->subdev.entity, num_pads,
diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h
index b43457fd2c43..4fc2cd1c6620 100644
--- a/drivers/media/platform/vsp1/vsp1_entity.h
+++ b/drivers/media/platform/vsp1/vsp1_entity.h
@@ -25,6 +25,7 @@ struct vsp1_pipeline;
 enum vsp1_entity_type {
 	VSP1_ENTITY_BRU,
 	VSP1_ENTITY_CLU,
+	VSP1_ENTITY_HGO,
 	VSP1_ENTITY_HSI,
 	VSP1_ENTITY_HST,
 	VSP1_ENTITY_LIF,
@@ -91,6 +92,7 @@ struct vsp1_entity {
 	struct media_pad *pads;
 	unsigned int source_pad;
 
+	struct media_entity **sources;
 	struct media_entity *sink;
 	unsigned int sink_pad;
 
@@ -129,9 +131,12 @@ vsp1_entity_get_pad_selection(struct vsp1_entity *entity,
 int vsp1_entity_init_cfg(struct v4l2_subdev *subdev,
 			 struct v4l2_subdev_pad_config *cfg);
 
-void vsp1_entity_route_setup(struct vsp1_entity *source,
+void vsp1_entity_route_setup(struct vsp1_entity *entity,
+			     struct vsp1_pipeline *pipe,
 			     struct vsp1_dl_list *dl);
 
+struct media_pad *vsp1_entity_remote_pad(struct media_pad *pad);
+
 int vsp1_subdev_get_pad_format(struct v4l2_subdev *subdev,
 			       struct v4l2_subdev_pad_config *cfg,
 			       struct v4l2_subdev_format *fmt);
diff --git a/drivers/media/platform/vsp1/vsp1_hgo.c b/drivers/media/platform/vsp1/vsp1_hgo.c
new file mode 100644
index 000000000000..94bb46f3e12b
--- /dev/null
+++ b/drivers/media/platform/vsp1/vsp1_hgo.c
@@ -0,0 +1,501 @@
+/*
+ * vsp1_hgo.c  --  R-Car VSP1 Histogram Generator 1D
+ *
+ * Copyright (C) 2016 Renesas Electronics Corporation
+ *
+ * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/device.h>
+#include <linux/gfp.h>
+
+#include <media/v4l2-subdev.h>
+#include <media/videobuf2-vmalloc.h>
+
+#include "vsp1.h"
+#include "vsp1_dl.h"
+#include "vsp1_hgo.h"
+
+#define HGO_MIN_SIZE				4U
+#define HGO_MAX_SIZE				8192U
+#define HGO_DATA_SIZE				((2 + 256) * 4)
+
+/* -----------------------------------------------------------------------------
+ * Device Access
+ */
+
+static inline u32 vsp1_hgo_read(struct vsp1_hgo *hgo, u32 reg)
+{
+	return vsp1_read(hgo->entity.vsp1, reg);
+}
+
+static inline void vsp1_hgo_write(struct vsp1_hgo *hgo, struct vsp1_dl_list *dl,
+				  u32 reg, u32 data)
+{
+	vsp1_dl_list_write(dl, reg, data);
+}
+
+/* -----------------------------------------------------------------------------
+ * Frame End Handler
+ */
+
+void vsp1_hgo_frame_end(struct vsp1_entity *entity)
+{
+	struct vsp1_hgo *hgo = to_hgo(&entity->subdev);
+	struct vsp1_histogram_buffer *buf;
+	unsigned int i;
+	size_t size;
+	u32 *data;
+
+	buf = vsp1_histogram_buffer_get(&hgo->histo);
+	if (!buf)
+		return;
+
+	data = buf->addr;
+
+	if (hgo->num_bins == 256) {
+		*data++ = vsp1_hgo_read(hgo, VI6_HGO_G_MAXMIN);
+		*data++ = vsp1_hgo_read(hgo, VI6_HGO_G_SUM);
+
+		for (i = 0; i < 256; ++i) {
+			vsp1_write(hgo->entity.vsp1, VI6_HGO_EXT_HIST_ADDR, i);
+			*data++ = vsp1_hgo_read(hgo, VI6_HGO_EXT_HIST_DATA);
+		}
+
+		size = (2 + 256) * sizeof(u32);
+	} else if (hgo->max_rgb) {
+		*data++ = vsp1_hgo_read(hgo, VI6_HGO_G_MAXMIN);
+		*data++ = vsp1_hgo_read(hgo, VI6_HGO_G_SUM);
+
+		for (i = 0; i < 64; ++i)
+			*data++ = vsp1_hgo_read(hgo, VI6_HGO_G_HISTO(i));
+
+		size = (2 + 64) * sizeof(u32);
+	} else {
+		*data++ = vsp1_hgo_read(hgo, VI6_HGO_R_MAXMIN);
+		*data++ = vsp1_hgo_read(hgo, VI6_HGO_G_MAXMIN);
+		*data++ = vsp1_hgo_read(hgo, VI6_HGO_B_MAXMIN);
+
+		*data++ = vsp1_hgo_read(hgo, VI6_HGO_R_SUM);
+		*data++ = vsp1_hgo_read(hgo, VI6_HGO_G_SUM);
+		*data++ = vsp1_hgo_read(hgo, VI6_HGO_B_SUM);
+
+		for (i = 0; i < 64; ++i) {
+			data[i] = vsp1_hgo_read(hgo, VI6_HGO_R_HISTO(i));
+			data[i+64] = vsp1_hgo_read(hgo, VI6_HGO_G_HISTO(i));
+			data[i+128] = vsp1_hgo_read(hgo, VI6_HGO_B_HISTO(i));
+		}
+
+		size = (6 + 64 * 3) * sizeof(u32);
+	}
+
+	vsp1_histogram_buffer_complete(&hgo->histo, buf, size);
+}
+
+/* -----------------------------------------------------------------------------
+ * Controls
+ */
+
+#define V4L2_CID_VSP1_HGO_MAX_RGB		(V4L2_CID_USER_BASE | 0x1001)
+#define V4L2_CID_VSP1_HGO_NUM_BINS		(V4L2_CID_USER_BASE | 0x1002)
+
+static const struct v4l2_ctrl_config hgo_max_rgb_control = {
+	.id = V4L2_CID_VSP1_HGO_MAX_RGB,
+	.name = "Maximum RGB Mode",
+	.type = V4L2_CTRL_TYPE_BOOLEAN,
+	.min = 0,
+	.max = 1,
+	.def = 0,
+	.step = 1,
+};
+
+static const s64 hgo_num_bins[] = {
+	64, 256,
+};
+
+static const struct v4l2_ctrl_config hgo_num_bins_control = {
+	.id = V4L2_CID_VSP1_HGO_NUM_BINS,
+	.name = "Number of Bins",
+	.type = V4L2_CTRL_TYPE_INTEGER_MENU,
+	.min = 0,
+	.max = 1,
+	.def = 0,
+	.qmenu_int = hgo_num_bins,
+};
+
+/* -----------------------------------------------------------------------------
+ * V4L2 Subdevice Operations
+ */
+
+static int hgo_enum_mbus_code(struct v4l2_subdev *subdev,
+			       struct v4l2_subdev_pad_config *cfg,
+			       struct v4l2_subdev_mbus_code_enum *code)
+{
+	static const unsigned int codes[] = {
+		MEDIA_BUS_FMT_ARGB8888_1X32,
+		MEDIA_BUS_FMT_AHSV8888_1X32,
+		MEDIA_BUS_FMT_AYUV8_1X32,
+	};
+
+	if (code->pad == HGO_PAD_SOURCE) {
+		code->code = MEDIA_BUS_FMT_FIXED;
+		return 0;
+	}
+
+	return vsp1_subdev_enum_mbus_code(subdev, cfg, code, codes,
+					  ARRAY_SIZE(codes));
+}
+
+static int hgo_enum_frame_size(struct v4l2_subdev *subdev,
+				struct v4l2_subdev_pad_config *cfg,
+				struct v4l2_subdev_frame_size_enum *fse)
+{
+	if (fse->pad != HGO_PAD_SINK)
+		return -EINVAL;
+
+	return vsp1_subdev_enum_frame_size(subdev, cfg, fse, HGO_MIN_SIZE,
+					   HGO_MIN_SIZE, HGO_MAX_SIZE,
+					   HGO_MAX_SIZE);
+}
+
+static int hgo_get_selection(struct v4l2_subdev *subdev,
+			     struct v4l2_subdev_pad_config *cfg,
+			     struct v4l2_subdev_selection *sel)
+{
+	struct vsp1_hgo *hgo = to_hgo(subdev);
+	struct v4l2_subdev_pad_config *config;
+	struct v4l2_mbus_framefmt *format;
+	struct v4l2_rect *crop;
+
+	if (sel->pad != HGO_PAD_SINK)
+		return -EINVAL;
+
+	config = vsp1_entity_get_pad_config(&hgo->entity, cfg, sel->which);
+	if (!config)
+		return -EINVAL;
+
+	switch (sel->target) {
+	case V4L2_SEL_TGT_COMPOSE_BOUNDS:
+	case V4L2_SEL_TGT_COMPOSE_DEFAULT:
+		crop = vsp1_entity_get_pad_selection(&hgo->entity, config,
+						     HGO_PAD_SINK,
+						     V4L2_SEL_TGT_CROP);
+		sel->r.left = 0;
+		sel->r.top = 0;
+		sel->r.width = crop->width;
+		sel->r.height = crop->height;
+		return 0;
+
+	case V4L2_SEL_TGT_CROP_BOUNDS:
+	case V4L2_SEL_TGT_CROP_DEFAULT:
+		format = vsp1_entity_get_pad_format(&hgo->entity, config,
+						    HGO_PAD_SINK);
+		sel->r.left = 0;
+		sel->r.top = 0;
+		sel->r.width = format->width;
+		sel->r.height = format->height;
+		return 0;
+
+	case V4L2_SEL_TGT_COMPOSE:
+	case V4L2_SEL_TGT_CROP:
+		sel->r = *vsp1_entity_get_pad_selection(&hgo->entity, config,
+							sel->pad, sel->target);
+		return 0;
+
+	default:
+		return -EINVAL;
+	}
+}
+
+static int hgo_set_crop(struct v4l2_subdev *subdev,
+			struct v4l2_subdev_pad_config *config,
+			struct v4l2_subdev_selection *sel)
+{
+	struct vsp1_hgo *hgo = to_hgo(subdev);
+	struct v4l2_mbus_framefmt *format;
+	struct v4l2_rect *selection;
+
+	/* The crop rectangle must be inside the input frame. */
+	format = vsp1_entity_get_pad_format(&hgo->entity, config, HGO_PAD_SINK);
+	sel->r.left = clamp_t(unsigned int, sel->r.left, 0, format->width - 1);
+	sel->r.top = clamp_t(unsigned int, sel->r.top, 0, format->height - 1);
+	sel->r.width = clamp_t(unsigned int, sel->r.width, HGO_MIN_SIZE,
+			       format->width - sel->r.left);
+	sel->r.height = clamp_t(unsigned int, sel->r.height, HGO_MIN_SIZE,
+				format->height - sel->r.top);
+
+	/* Set the crop rectangle and reset the compose rectangle. */
+	selection = vsp1_entity_get_pad_selection(&hgo->entity, config,
+						  sel->pad, V4L2_SEL_TGT_CROP);
+	*selection = sel->r;
+
+	selection = vsp1_entity_get_pad_selection(&hgo->entity, config,
+						  sel->pad,
+						  V4L2_SEL_TGT_COMPOSE);
+	*selection = sel->r;
+
+	return 0;
+}
+
+static int hgo_set_compose(struct v4l2_subdev *subdev,
+			   struct v4l2_subdev_pad_config *config,
+			   struct v4l2_subdev_selection *sel)
+{
+	struct vsp1_hgo *hgo = to_hgo(subdev);
+	struct v4l2_rect *compose;
+	struct v4l2_rect *crop;
+	unsigned int ratio;
+
+	/* The compose rectangle is used to configure downscaling, the top left
+	 * corner is fixed to (0,0) and the size to 1/2 or 1/4 of the crop
+	 * rectangle.
+	 */
+	sel->r.left = 0;
+	sel->r.top = 0;
+
+	crop = vsp1_entity_get_pad_selection(&hgo->entity, config, sel->pad,
+					     V4L2_SEL_TGT_CROP);
+
+	/* Clamp the width and height to acceptable values first and then
+	 * compute the closest rounded dividing ratio.
+	 *
+	 * Ratio	Rounded ratio
+	 * --------------------------
+	 * [1.0 1.5[	1
+	 * [1.5 3.0[	2
+	 * [3.0 4.0]	4
+	 *
+	 * The rounded ratio can be computed using
+	 *
+	 * 1 << (ceil(ratio * 2) / 3)
+	 */
+	sel->r.width = clamp(sel->r.width, crop->width / 4, crop->width);
+	ratio = 1 << (crop->width * 2 / sel->r.width / 3);
+	sel->r.width = crop->width / ratio;
+
+
+	sel->r.height = clamp(sel->r.height, crop->height / 4, crop->height);
+	ratio = 1 << (crop->height * 2 / sel->r.height / 3);
+	sel->r.height = crop->height / ratio;
+
+	compose = vsp1_entity_get_pad_selection(&hgo->entity, config, sel->pad,
+						V4L2_SEL_TGT_COMPOSE);
+	*compose = sel->r;
+
+	return 0;
+}
+
+static int hgo_set_selection(struct v4l2_subdev *subdev,
+			     struct v4l2_subdev_pad_config *cfg,
+			     struct v4l2_subdev_selection *sel)
+{
+	struct vsp1_hgo *hgo = to_hgo(subdev);
+	struct v4l2_subdev_pad_config *config;
+
+	if (sel->pad != HGO_PAD_SINK)
+		return -EINVAL;
+
+	config = vsp1_entity_get_pad_config(&hgo->entity, cfg, sel->which);
+	if (!config)
+		return -EINVAL;
+
+	if (sel->target == V4L2_SEL_TGT_CROP)
+		return hgo_set_crop(subdev, config, sel);
+	else if (sel->target == V4L2_SEL_TGT_COMPOSE)
+		return hgo_set_compose(subdev, config, sel);
+	else
+		return -EINVAL;
+}
+
+static int hgo_get_format(struct v4l2_subdev *subdev,
+			   struct v4l2_subdev_pad_config *cfg,
+			   struct v4l2_subdev_format *fmt)
+{
+	if (fmt->pad == HGO_PAD_SOURCE) {
+		fmt->format.code = MEDIA_BUS_FMT_FIXED;
+		fmt->format.width = 0;
+		fmt->format.height = 0;
+		fmt->format.field = V4L2_FIELD_NONE;
+		fmt->format.colorspace = V4L2_COLORSPACE_RAW;
+		return 0;
+	}
+
+	return vsp1_subdev_get_pad_format(subdev, cfg, fmt);
+}
+
+static int hgo_set_format(struct v4l2_subdev *subdev,
+			   struct v4l2_subdev_pad_config *cfg,
+			   struct v4l2_subdev_format *fmt)
+{
+	struct vsp1_hgo *hgo = to_hgo(subdev);
+	struct v4l2_subdev_pad_config *config;
+	struct v4l2_mbus_framefmt *format;
+	struct v4l2_rect *selection;
+
+	if (fmt->pad != HGO_PAD_SINK)
+		return hgo_get_format(subdev, cfg, fmt);
+
+	config = vsp1_entity_get_pad_config(&hgo->entity, cfg, fmt->which);
+	if (!config)
+		return -EINVAL;
+
+	/* Default to YUV if the requested format is not supported. */
+	if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
+	    fmt->format.code != MEDIA_BUS_FMT_AHSV8888_1X32 &&
+	    fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32)
+		fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32;
+
+	format = vsp1_entity_get_pad_format(&hgo->entity, config, fmt->pad);
+
+	format->code = fmt->format.code;
+	format->width = clamp_t(unsigned int, fmt->format.width,
+				HGO_MIN_SIZE, HGO_MAX_SIZE);
+	format->height = clamp_t(unsigned int, fmt->format.height,
+				 HGO_MIN_SIZE, HGO_MAX_SIZE);
+	format->field = V4L2_FIELD_NONE;
+	format->colorspace = V4L2_COLORSPACE_SRGB;
+
+	fmt->format = *format;
+
+	/* Reset the crop and compose rectangles */
+	selection = vsp1_entity_get_pad_selection(&hgo->entity, config,
+						  fmt->pad, V4L2_SEL_TGT_CROP);
+	selection->left = 0;
+	selection->top = 0;
+	selection->width = format->width;
+	selection->height = format->height;
+
+	selection = vsp1_entity_get_pad_selection(&hgo->entity, config,
+						  fmt->pad,
+						  V4L2_SEL_TGT_COMPOSE);
+	selection->left = 0;
+	selection->top = 0;
+	selection->width = format->width;
+	selection->height = format->height;
+
+	return 0;
+}
+
+static const struct v4l2_subdev_pad_ops hgo_pad_ops = {
+	.enum_mbus_code = hgo_enum_mbus_code,
+	.enum_frame_size = hgo_enum_frame_size,
+	.get_fmt = hgo_get_format,
+	.set_fmt = hgo_set_format,
+	.get_selection = hgo_get_selection,
+	.set_selection = hgo_set_selection,
+};
+
+static const struct v4l2_subdev_ops hgo_ops = {
+	.pad    = &hgo_pad_ops,
+};
+
+/* -----------------------------------------------------------------------------
+ * VSP1 Entity Operations
+ */
+
+static void hgo_configure(struct vsp1_entity *entity,
+			  struct vsp1_pipeline *pipe,
+			  struct vsp1_dl_list *dl, bool full)
+{
+	struct vsp1_hgo *hgo = to_hgo(&entity->subdev);
+	struct v4l2_rect *compose;
+	struct v4l2_rect *crop;
+	unsigned int hratio;
+	unsigned int vratio;
+
+	if (!full)
+		return;
+
+	crop = vsp1_entity_get_pad_selection(entity, entity->config,
+					     HGO_PAD_SINK, V4L2_SEL_TGT_CROP);
+	compose = vsp1_entity_get_pad_selection(entity, entity->config,
+						HGO_PAD_SINK,
+						V4L2_SEL_TGT_COMPOSE);
+
+	vsp1_hgo_write(hgo, dl, VI6_HGO_REGRST, VI6_HGO_REGRST_RCLEA);
+
+	vsp1_hgo_write(hgo, dl, VI6_HGO_OFFSET,
+		       (crop->left << VI6_HGO_OFFSET_HOFFSET_SHIFT) |
+		       (crop->top << VI6_HGO_OFFSET_VOFFSET_SHIFT));
+	vsp1_hgo_write(hgo, dl, VI6_HGO_SIZE,
+		       (crop->width << VI6_HGO_SIZE_HSIZE_SHIFT) |
+		       (crop->height << VI6_HGO_SIZE_VSIZE_SHIFT));
+
+	mutex_lock(hgo->ctrls.handler.lock);
+	hgo->max_rgb = hgo->ctrls.max_rgb->cur.val;
+	if (hgo->ctrls.num_bins)
+		hgo->num_bins = hgo_num_bins[hgo->ctrls.num_bins->cur.val];
+	mutex_unlock(hgo->ctrls.handler.lock);
+
+	hratio = crop->width * 2 / compose->width / 3;
+	vratio = crop->height * 2 / compose->height / 3;
+	vsp1_hgo_write(hgo, dl, VI6_HGO_MODE,
+		       (hgo->num_bins == 256 ? VI6_HGO_MODE_STEP : 0) |
+		       (hgo->max_rgb ? VI6_HGO_MODE_MAXRGB : 0) |
+		       (hratio << VI6_HGO_MODE_HRATIO_SHIFT) |
+		       (vratio << VI6_HGO_MODE_VRATIO_SHIFT));
+}
+
+static void hgo_destroy(struct vsp1_entity *entity)
+{
+	struct vsp1_hgo *hgo = to_hgo(&entity->subdev);
+
+	vsp1_histogram_cleanup(&hgo->histo);
+}
+
+static const struct vsp1_entity_operations hgo_entity_ops = {
+	.configure = hgo_configure,
+	.destroy = hgo_destroy,
+};
+
+/* -----------------------------------------------------------------------------
+ * Initialization and Cleanup
+ */
+
+struct vsp1_hgo *vsp1_hgo_create(struct vsp1_device *vsp1)
+{
+	struct vsp1_hgo *hgo;
+	int ret;
+
+	hgo = devm_kzalloc(vsp1->dev, sizeof(*hgo), GFP_KERNEL);
+	if (hgo == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	hgo->entity.ops = &hgo_entity_ops;
+	hgo->entity.type = VSP1_ENTITY_HGO;
+
+	ret = vsp1_entity_init(vsp1, &hgo->entity, "hgo", 2, &hgo_ops,
+			       MEDIA_ENT_F_PROC_VIDEO_STATISTICS);
+	if (ret < 0)
+		return ERR_PTR(ret);
+
+	/* Initialize the control handler. */
+	v4l2_ctrl_handler_init(&hgo->ctrls.handler,
+			       vsp1->info->gen == 3 ? 2 : 1);
+	hgo->ctrls.max_rgb = v4l2_ctrl_new_custom(&hgo->ctrls.handler,
+						  &hgo_max_rgb_control, NULL);
+	if (vsp1->info->gen == 3)
+		hgo->ctrls.num_bins =
+			v4l2_ctrl_new_custom(&hgo->ctrls.handler,
+					     &hgo_num_bins_control, NULL);
+
+	hgo->max_rgb = false;
+	hgo->num_bins = 64;
+
+	hgo->entity.subdev.ctrl_handler = &hgo->ctrls.handler;
+
+	/* Initialize the video device and queue for statistics data. */
+	ret = vsp1_histogram_init(vsp1, &hgo->histo, hgo->entity.subdev.name,
+				  HGO_DATA_SIZE, V4L2_META_FMT_VSP1_HGO);
+	if (ret < 0) {
+		vsp1_entity_destroy(&hgo->entity);
+		return ERR_PTR(ret);
+	}
+
+	return hgo;
+}
diff --git a/drivers/media/platform/vsp1/vsp1_hgo.h b/drivers/media/platform/vsp1/vsp1_hgo.h
new file mode 100644
index 000000000000..d677b3fe6023
--- /dev/null
+++ b/drivers/media/platform/vsp1/vsp1_hgo.h
@@ -0,0 +1,50 @@
+/*
+ * vsp1_hgo.h  --  R-Car VSP1 Histogram Generator 1D
+ *
+ * Copyright (C) 2016 Renesas Electronics Corporation
+ *
+ * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef __VSP1_HGO_H__
+#define __VSP1_HGO_H__
+
+#include <media/media-entity.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-subdev.h>
+
+#include "vsp1_entity.h"
+#include "vsp1_histo.h"
+
+struct vsp1_device;
+
+#define HGO_PAD_SINK				0
+#define HGO_PAD_SOURCE				1
+
+struct vsp1_hgo {
+	struct vsp1_entity entity;
+	struct vsp1_histogram histo;
+
+	struct {
+		struct v4l2_ctrl_handler handler;
+		struct v4l2_ctrl *max_rgb;
+		struct v4l2_ctrl *num_bins;
+	} ctrls;
+
+	bool max_rgb;
+	unsigned int num_bins;
+};
+
+static inline struct vsp1_hgo *to_hgo(struct v4l2_subdev *subdev)
+{
+	return container_of(subdev, struct vsp1_hgo, entity.subdev);
+}
+
+struct vsp1_hgo *vsp1_hgo_create(struct vsp1_device *vsp1);
+void vsp1_hgo_frame_end(struct vsp1_entity *hgo);
+
+#endif /* __VSP1_HGO_H__ */
diff --git a/drivers/media/platform/vsp1/vsp1_histo.c b/drivers/media/platform/vsp1/vsp1_histo.c
new file mode 100644
index 000000000000..89e162438bd6
--- /dev/null
+++ b/drivers/media/platform/vsp1/vsp1_histo.c
@@ -0,0 +1,324 @@
+/*
+ * vsp1_histo.c  --  R-Car VSP1 Histogram API
+ *
+ * Copyright (C) 2016 Renesas Electronics Corporation
+ * Copyright (C) 2016 Laurent Pinchart
+ *
+ * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/device.h>
+#include <linux/gfp.h>
+
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-subdev.h>
+#include <media/videobuf2-vmalloc.h>
+
+#include "vsp1.h"
+#include "vsp1_histo.h"
+#include "vsp1_pipe.h"
+
+/* -----------------------------------------------------------------------------
+ * Buffer Operations
+ */
+
+static inline struct vsp1_histogram_buffer *
+to_vsp1_histogram_buffer(struct vb2_v4l2_buffer *vbuf)
+{
+	return container_of(vbuf, struct vsp1_histogram_buffer, buf);
+}
+
+struct vsp1_histogram_buffer *
+vsp1_histogram_buffer_get(struct vsp1_histogram *histo)
+{
+	struct vsp1_histogram_buffer *buf = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&histo->irqlock, flags);
+
+	if (list_empty(&histo->irqqueue))
+		goto done;
+
+	buf = list_first_entry(&histo->irqqueue, struct vsp1_histogram_buffer,
+			       queue);
+	list_del(&buf->queue);
+	histo->readout = true;
+
+done:
+	spin_unlock_irqrestore(&histo->irqlock, flags);
+	return buf;
+}
+
+void vsp1_histogram_buffer_complete(struct vsp1_histogram *histo,
+				    struct vsp1_histogram_buffer *buf,
+				    size_t size)
+{
+	struct vsp1_pipeline *pipe = histo->pipe;
+	unsigned long flags;
+
+	/* The pipeline pointer is guaranteed to be valid as this function is
+	 * called from the frame completion interrupt handler, which can only
+	 * occur when video streaming is active.
+	 */
+	buf->buf.sequence = pipe->sequence;
+	buf->buf.vb2_buf.timestamp = ktime_get_ns();
+	vb2_set_plane_payload(&buf->buf.vb2_buf, 0, size);
+	vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_DONE);
+
+	spin_lock_irqsave(&histo->irqlock, flags);
+	histo->readout = false;
+	wake_up(&histo->wait_queue);
+	spin_unlock_irqrestore(&histo->irqlock, flags);
+}
+
+/* -----------------------------------------------------------------------------
+ * videobuf2 Queue Operations
+ */
+
+static int histo_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
+			     unsigned int *nplanes, unsigned int sizes[],
+			     struct device *alloc_devs[])
+{
+	struct vsp1_histogram *histo = vb2_get_drv_priv(vq);
+
+	if (*nplanes) {
+		if (*nplanes != 1)
+			return -EINVAL;
+
+		if (sizes[0] < histo->data_size)
+			return -EINVAL;
+
+		return 0;
+	}
+
+	*nplanes = 1;
+	sizes[0] = histo->data_size;
+
+	return 0;
+}
+
+static int histo_buffer_prepare(struct vb2_buffer *vb)
+{
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct vsp1_histogram *histo = vb2_get_drv_priv(vb->vb2_queue);
+	struct vsp1_histogram_buffer *buf = to_vsp1_histogram_buffer(vbuf);
+
+	if (vb->num_planes != 1)
+		return -EINVAL;
+
+	if (vb2_plane_size(vb, 0) < histo->data_size)
+		return -EINVAL;
+
+	buf->addr = vb2_plane_vaddr(vb, 0);
+
+	return 0;
+}
+
+static void histo_buffer_queue(struct vb2_buffer *vb)
+{
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct vsp1_histogram *histo = vb2_get_drv_priv(vb->vb2_queue);
+	struct vsp1_histogram_buffer *buf = to_vsp1_histogram_buffer(vbuf);
+	unsigned long flags;
+
+	spin_lock_irqsave(&histo->irqlock, flags);
+	list_add_tail(&buf->queue, &histo->irqqueue);
+	spin_unlock_irqrestore(&histo->irqlock, flags);
+}
+
+static int histo_start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+	return 0;
+}
+
+static void histo_stop_streaming(struct vb2_queue *vq)
+{
+	struct vsp1_histogram *histo = vb2_get_drv_priv(vq);
+	struct vsp1_histogram_buffer *buffer;
+	unsigned long flags;
+
+	spin_lock_irqsave(&histo->irqlock, flags);
+
+	/* Remove all buffers from the IRQ queue. */
+	list_for_each_entry(buffer, &histo->irqqueue, queue)
+		vb2_buffer_done(&buffer->buf.vb2_buf, VB2_BUF_STATE_ERROR);
+	INIT_LIST_HEAD(&histo->irqqueue);
+
+	/* Wait for the buffer being read out (if any) to complete. */
+	wait_event_lock_irq(histo->wait_queue, !histo->readout, histo->irqlock);
+
+	spin_unlock_irqrestore(&histo->irqlock, flags);
+}
+
+static const struct vb2_ops histo_video_queue_qops = {
+	.queue_setup = histo_queue_setup,
+	.buf_prepare = histo_buffer_prepare,
+	.buf_queue = histo_buffer_queue,
+	.wait_prepare = vb2_ops_wait_prepare,
+	.wait_finish = vb2_ops_wait_finish,
+	.start_streaming = histo_start_streaming,
+	.stop_streaming = histo_stop_streaming,
+};
+
+/* -----------------------------------------------------------------------------
+ * V4L2 ioctls
+ */
+
+static int histo_v4l2_querycap(struct file *file, void *fh,
+			       struct v4l2_capability *cap)
+{
+	struct v4l2_fh *vfh = file->private_data;
+	struct vsp1_histogram *histo = to_vsp1_histo(vfh->vdev);
+
+	cap->capabilities = V4L2_CAP_DEVICE_CAPS | V4L2_CAP_STREAMING
+			  | V4L2_CAP_VIDEO_CAPTURE_MPLANE
+			  | V4L2_CAP_VIDEO_OUTPUT_MPLANE
+			  | V4L2_CAP_META_CAPTURE;
+	cap->device_caps = V4L2_CAP_META_CAPTURE
+			 | V4L2_CAP_STREAMING;
+
+	strlcpy(cap->driver, "vsp1", sizeof(cap->driver));
+	strlcpy(cap->card, histo->video.name, sizeof(cap->card));
+	snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
+		 dev_name(histo->vsp1->dev));
+
+	return 0;
+}
+
+static int histo_v4l2_enum_format(struct file *file, void *fh,
+				  struct v4l2_fmtdesc *f)
+{
+	struct v4l2_fh *vfh = file->private_data;
+	struct vsp1_histogram *histo = to_vsp1_histo(vfh->vdev);
+
+	if (f->index > 0 || f->type != histo->queue.type)
+		return -EINVAL;
+
+	f->pixelformat = histo->format;
+
+	return 0;
+}
+
+static int histo_v4l2_get_format(struct file *file, void *fh,
+				 struct v4l2_format *format)
+{
+	struct v4l2_fh *vfh = file->private_data;
+	struct vsp1_histogram *histo = to_vsp1_histo(vfh->vdev);
+	struct v4l2_meta_format *meta = &format->fmt.meta;
+
+	if (format->type != histo->queue.type)
+		return -EINVAL;
+
+	memset(meta, 0, sizeof(*meta));
+
+	meta->dataformat = histo->format;
+	meta->buffersize = histo->data_size;
+
+	return 0;
+}
+
+static const struct v4l2_ioctl_ops histo_v4l2_ioctl_ops = {
+	.vidioc_querycap		= histo_v4l2_querycap,
+	.vidioc_enum_fmt_meta_cap	= histo_v4l2_enum_format,
+	.vidioc_g_fmt_meta_cap		= histo_v4l2_get_format,
+	.vidioc_s_fmt_meta_cap		= histo_v4l2_get_format,
+	.vidioc_try_fmt_meta_cap	= histo_v4l2_get_format,
+	.vidioc_reqbufs			= vb2_ioctl_reqbufs,
+	.vidioc_querybuf		= vb2_ioctl_querybuf,
+	.vidioc_qbuf			= vb2_ioctl_qbuf,
+	.vidioc_dqbuf			= vb2_ioctl_dqbuf,
+	.vidioc_create_bufs		= vb2_ioctl_create_bufs,
+	.vidioc_prepare_buf		= vb2_ioctl_prepare_buf,
+	.vidioc_streamon		= vb2_ioctl_streamon,
+	.vidioc_streamoff		= vb2_ioctl_streamoff,
+};
+
+/* -----------------------------------------------------------------------------
+ * V4L2 File Operations
+ */
+
+static const struct v4l2_file_operations histo_v4l2_fops = {
+	.owner = THIS_MODULE,
+	.unlocked_ioctl = video_ioctl2,
+	.open = v4l2_fh_open,
+	.release = vb2_fop_release,
+	.poll = vb2_fop_poll,
+	.mmap = vb2_fop_mmap,
+};
+
+int vsp1_histogram_init(struct vsp1_device *vsp1, struct vsp1_histogram *histo,
+			const char *name, size_t data_size, u32 format)
+{
+	int ret;
+
+	histo->vsp1 = vsp1;
+	histo->data_size = data_size;
+	histo->format = format;
+
+	histo->pad.flags = MEDIA_PAD_FL_SINK;
+	histo->video.vfl_dir = VFL_DIR_RX;
+
+	mutex_init(&histo->lock);
+	spin_lock_init(&histo->irqlock);
+	INIT_LIST_HEAD(&histo->irqqueue);
+	init_waitqueue_head(&histo->wait_queue);
+
+	/* Initialize the media entity... */
+	ret = media_entity_pads_init(&histo->video.entity, 1, &histo->pad);
+	if (ret < 0)
+		return ret;
+
+	/* ... and the video node... */
+	histo->video.v4l2_dev = &vsp1->v4l2_dev;
+	histo->video.fops = &histo_v4l2_fops;
+	snprintf(histo->video.name, sizeof(histo->video.name),
+		 "%s histo", name);
+	histo->video.vfl_type = VFL_TYPE_GRABBER;
+	histo->video.release = video_device_release_empty;
+	histo->video.ioctl_ops = &histo_v4l2_ioctl_ops;
+
+	video_set_drvdata(&histo->video, histo);
+
+	/* ... and the buffers queue... */
+	histo->queue.type = V4L2_BUF_TYPE_META_CAPTURE;
+	histo->queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
+	histo->queue.lock = &histo->lock;
+	histo->queue.drv_priv = histo;
+	histo->queue.buf_struct_size = sizeof(struct vsp1_histogram_buffer);
+	histo->queue.ops = &histo_video_queue_qops;
+	histo->queue.mem_ops = &vb2_vmalloc_memops;
+	histo->queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	histo->queue.dev = histo->vsp1->dev;
+	ret = vb2_queue_init(&histo->queue);
+	if (ret < 0) {
+		dev_err(histo->vsp1->dev, "failed to initialize vb2 queue\n");
+		goto error;
+	}
+
+	/* ... and register the video device. */
+	histo->video.queue = &histo->queue;
+	ret = video_register_device(&histo->video, VFL_TYPE_GRABBER, -1);
+	if (ret < 0) {
+		dev_err(histo->vsp1->dev, "failed to register video device\n");
+		goto error;
+	}
+
+	return 0;
+
+error:
+	vsp1_histogram_cleanup(histo);
+	return ret;
+}
+
+void vsp1_histogram_cleanup(struct vsp1_histogram *histo)
+{
+	if (video_is_registered(&histo->video))
+		video_unregister_device(&histo->video);
+
+	media_entity_cleanup(&histo->video.entity);
+}
diff --git a/drivers/media/platform/vsp1/vsp1_histo.h b/drivers/media/platform/vsp1/vsp1_histo.h
new file mode 100644
index 000000000000..daf648c490f5
--- /dev/null
+++ b/drivers/media/platform/vsp1/vsp1_histo.h
@@ -0,0 +1,69 @@
+/*
+ * vsp1_histo.h  --  R-Car VSP1 Histogram API
+ *
+ * Copyright (C) 2016 Renesas Electronics Corporation
+ * Copyright (C) 2016 Laurent Pinchart
+ *
+ * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef __VSP1_HISTO_H__
+#define __VSP1_HISTO_H__
+
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+
+#include <media/media-entity.h>
+#include <media/v4l2-dev.h>
+#include <media/videobuf2-v4l2.h>
+
+struct vsp1_device;
+struct vsp1_pipeline;
+
+struct vsp1_histogram_buffer {
+	struct vb2_v4l2_buffer buf;
+	struct list_head queue;
+	void *addr;
+};
+
+struct vsp1_histogram {
+	struct vsp1_device *vsp1;
+	struct vsp1_pipeline *pipe;
+
+	struct video_device video;
+	struct media_pad pad;
+
+	size_t data_size;
+	u32 format;
+
+	struct mutex lock;
+	struct vb2_queue queue;
+
+	spinlock_t irqlock;
+	struct list_head irqqueue;
+
+	wait_queue_head_t wait_queue;
+	bool readout;
+};
+
+static inline struct vsp1_histogram *to_vsp1_histo(struct video_device *vdev)
+{
+	return container_of(vdev, struct vsp1_histogram, video);
+}
+
+int vsp1_histogram_init(struct vsp1_device *vsp1, struct vsp1_histogram *histo,
+			const char *name, size_t data_size, u32 format);
+void vsp1_histogram_cleanup(struct vsp1_histogram *histo);
+
+struct vsp1_histogram_buffer *
+vsp1_histogram_buffer_get(struct vsp1_histogram *histo);
+void vsp1_histogram_buffer_complete(struct vsp1_histogram *histo,
+				    struct vsp1_histogram_buffer *buf,
+				    size_t size);
+
+#endif /* __VSP1_HISTO_H__ */
diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c
index 3e75fb3fcace..0dd7c163c8d5 100644
--- a/drivers/media/platform/vsp1/vsp1_pipe.c
+++ b/drivers/media/platform/vsp1/vsp1_pipe.c
@@ -23,6 +23,7 @@
 #include "vsp1_bru.h"
 #include "vsp1_dl.h"
 #include "vsp1_entity.h"
+#include "vsp1_hgo.h"
 #include "vsp1_pipe.h"
 #include "vsp1_rwpf.h"
 #include "vsp1_uds.h"
@@ -184,11 +185,18 @@ void vsp1_pipeline_reset(struct vsp1_pipeline *pipe)
 		pipe->output = NULL;
 	}
 
+	if (pipe->hgo) {
+		struct vsp1_hgo *hgo = to_hgo(&pipe->hgo->subdev);
+
+		hgo->histo.pipe = NULL;
+	}
+
 	INIT_LIST_HEAD(&pipe->entities);
 	pipe->state = VSP1_PIPELINE_STOPPED;
 	pipe->buffers_ready = 0;
 	pipe->num_inputs = 0;
 	pipe->bru = NULL;
+	pipe->hgo = NULL;
 	pipe->lif = NULL;
 	pipe->uds = NULL;
 }
@@ -232,6 +240,7 @@ bool vsp1_pipeline_stopped(struct vsp1_pipeline *pipe)
 
 int vsp1_pipeline_stop(struct vsp1_pipeline *pipe)
 {
+	struct vsp1_device *vsp1 = pipe->output->entity.vsp1;
 	struct vsp1_entity *entity;
 	unsigned long flags;
 	int ret;
@@ -240,8 +249,7 @@ int vsp1_pipeline_stop(struct vsp1_pipeline *pipe)
 		/* When using display lists in continuous frame mode the only
 		 * way to stop the pipeline is to reset the hardware.
 		 */
-		ret = vsp1_reset_wpf(pipe->output->entity.vsp1,
-				     pipe->output->entity.index);
+		ret = vsp1_reset_wpf(vsp1, pipe->output->entity.index);
 		if (ret == 0) {
 			spin_lock_irqsave(&pipe->irqlock, flags);
 			pipe->state = VSP1_PIPELINE_STOPPED;
@@ -261,10 +269,15 @@ int vsp1_pipeline_stop(struct vsp1_pipeline *pipe)
 
 	list_for_each_entry(entity, &pipe->entities, list_pipe) {
 		if (entity->route && entity->route->reg)
-			vsp1_write(entity->vsp1, entity->route->reg,
+			vsp1_write(vsp1, entity->route->reg,
 				   VI6_DPR_NODE_UNUSED);
 	}
 
+	if (pipe->hgo)
+		vsp1_write(vsp1, VI6_DPR_HGO_SMPPT,
+			   (7 << VI6_DPR_SMPPT_TGW_SHIFT) |
+			   (VI6_DPR_NODE_UNUSED << VI6_DPR_SMPPT_PT_SHIFT));
+
 	v4l2_subdev_call(&pipe->output->entity.subdev, video, s_stream, 0);
 
 	return ret;
@@ -288,6 +301,9 @@ void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe)
 
 	vsp1_dlm_irq_frame_end(pipe->output->dlm);
 
+	if (pipe->hgo)
+		vsp1_hgo_frame_end(pipe->hgo);
+
 	if (pipe->frame_end)
 		pipe->frame_end(pipe);
 
diff --git a/drivers/media/platform/vsp1/vsp1_pipe.h b/drivers/media/platform/vsp1/vsp1_pipe.h
index d20d997b1fda..bd42effe405e 100644
--- a/drivers/media/platform/vsp1/vsp1_pipe.h
+++ b/drivers/media/platform/vsp1/vsp1_pipe.h
@@ -72,6 +72,7 @@ enum vsp1_pipeline_state {
  * @inputs: array of RPFs in the pipeline (indexed by RPF index)
  * @output: WPF at the output of the pipeline
  * @bru: BRU entity, if present
+ * @hgo: HGO entity, if present
  * @lif: LIF entity, if present
  * @uds: UDS entity, if present
  * @uds_input: entity at the input of the UDS, if the UDS is present
@@ -97,6 +98,7 @@ struct vsp1_pipeline {
 	struct vsp1_rwpf *inputs[VSP1_MAX_RPF];
 	struct vsp1_rwpf *output;
 	struct vsp1_entity *bru;
+	struct vsp1_entity *hgo;
 	struct vsp1_entity *lif;
 	struct vsp1_entity *uds;
 	struct vsp1_entity *uds_input;
diff --git a/drivers/media/platform/vsp1/vsp1_regs.h b/drivers/media/platform/vsp1/vsp1_regs.h
index 3b03007ba625..d8213481edbe 100644
--- a/drivers/media/platform/vsp1/vsp1_regs.h
+++ b/drivers/media/platform/vsp1/vsp1_regs.h
@@ -328,8 +328,8 @@
 #define VI6_DPR_ROUTE_RT_MASK		(0x3f << 0)
 #define VI6_DPR_ROUTE_RT_SHIFT		0
 
-#define VI6_DPR_HGO_SMPPT		0x2050
-#define VI6_DPR_HGT_SMPPT		0x2054
+#define VI6_DPR_HGO_SMPPT		0x2054
+#define VI6_DPR_HGT_SMPPT		0x2058
 #define VI6_DPR_SMPPT_TGW_MASK		(7 << 8)
 #define VI6_DPR_SMPPT_TGW_SHIFT		8
 #define VI6_DPR_SMPPT_PT_MASK		(0x3f << 0)
@@ -590,24 +590,38 @@
  */
 
 #define VI6_HGO_OFFSET			0x3000
+#define VI6_HGO_OFFSET_HOFFSET_SHIFT	16
+#define VI6_HGO_OFFSET_VOFFSET_SHIFT	0
 #define VI6_HGO_SIZE			0x3004
+#define VI6_HGO_SIZE_HSIZE_SHIFT	16
+#define VI6_HGO_SIZE_VSIZE_SHIFT	0
 #define VI6_HGO_MODE			0x3008
+#define VI6_HGO_MODE_STEP		(1 << 10)
+#define VI6_HGO_MODE_MAXRGB		(1 << 7)
+#define VI6_HGO_MODE_OFSB_R		(1 << 6)
+#define VI6_HGO_MODE_OFSB_G		(1 << 5)
+#define VI6_HGO_MODE_OFSB_B		(1 << 4)
+#define VI6_HGO_MODE_HRATIO_SHIFT	2
+#define VI6_HGO_MODE_VRATIO_SHIFT	0
 #define VI6_HGO_LB_TH			0x300c
 #define VI6_HGO_LBn_H(n)		(0x3010 + (n) * 8)
 #define VI6_HGO_LBn_V(n)		(0x3014 + (n) * 8)
-#define VI6_HGO_R_HISTO			0x3030
+#define VI6_HGO_R_HISTO(n)		(0x3030 + (n) * 4)
 #define VI6_HGO_R_MAXMIN		0x3130
 #define VI6_HGO_R_SUM			0x3134
 #define VI6_HGO_R_LB_DET		0x3138
-#define VI6_HGO_G_HISTO			0x3140
+#define VI6_HGO_G_HISTO(n)		(0x3140 + (n) * 4)
 #define VI6_HGO_G_MAXMIN		0x3240
 #define VI6_HGO_G_SUM			0x3244
 #define VI6_HGO_G_LB_DET		0x3248
-#define VI6_HGO_B_HISTO			0x3250
+#define VI6_HGO_B_HISTO(n)		(0x3250 + (n) * 4)
 #define VI6_HGO_B_MAXMIN		0x3350
 #define VI6_HGO_B_SUM			0x3354
 #define VI6_HGO_B_LB_DET		0x3358
+#define VI6_HGO_EXT_HIST_ADDR		0x335c
+#define VI6_HGO_EXT_HIST_DATA		0x3360
 #define VI6_HGO_REGRST			0x33fc
+#define VI6_HGO_REGRST_RCLEA		(1 << 0)
 
 /* -----------------------------------------------------------------------------
  * HGT Control Registers
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index 9fb4fc26a359..75e6e6c6b664 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -31,6 +31,7 @@
 #include "vsp1_bru.h"
 #include "vsp1_dl.h"
 #include "vsp1_entity.h"
+#include "vsp1_hgo.h"
 #include "vsp1_pipe.h"
 #include "vsp1_rwpf.h"
 #include "vsp1_uds.h"
@@ -325,7 +326,11 @@ static int vsp1_video_pipeline_build_branch(struct vsp1_pipeline *pipe,
 	if (ret < 0)
 		return ret;
 
-	pad = media_entity_remote_pad(&input->entity.pads[RWPF_PAD_SOURCE]);
+	/* The main data path doesn't include the HGO, use
+	 * vsp1_entity_remote_pad() to traverse the graph.
+	 */
+
+	pad = vsp1_entity_remote_pad(&input->entity.pads[RWPF_PAD_SOURCE]);
 
 	while (1) {
 		if (pad == NULL) {
@@ -377,13 +382,9 @@ static int vsp1_video_pipeline_build_branch(struct vsp1_pipeline *pipe,
 					: &input->entity;
 		}
 
-		/* Follow the source link. The link setup operations ensure
-		 * that the output fan-out can't be more than one, there is thus
-		 * no need to verify here that only a single source link is
-		 * activated.
-		 */
+		/* Follow the source link, ignoring any HGO. */
 		pad = &entity->pads[entity->source_pad];
-		pad = media_entity_remote_pad(pad);
+		pad = vsp1_entity_remote_pad(pad);
 	}
 
 	/* The last entity must be the output WPF. */
@@ -438,6 +439,11 @@ static int vsp1_video_pipeline_build(struct vsp1_pipeline *pipe,
 			pipe->lif = e;
 		} else if (e->type == VSP1_ENTITY_BRU) {
 			pipe->bru = e;
+		} else if (e->type == VSP1_ENTITY_HGO) {
+			struct vsp1_hgo *hgo = to_hgo(subdev);
+
+			pipe->hgo = e;
+			hgo->histo.pipe = pipe;
 		}
 	}
 
@@ -631,7 +637,7 @@ static int vsp1_video_setup_pipeline(struct vsp1_pipeline *pipe)
 	}
 
 	list_for_each_entry(entity, &pipe->entities, list_pipe) {
-		vsp1_entity_route_setup(entity, pipe->dl);
+		vsp1_entity_route_setup(entity, pipe, pipe->dl);
 
 		if (entity->ops->configure)
 			entity->ops->configure(entity, pipe, pipe->dl, true);
-- 
Regards,

Laurent Pinchart


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 4/4] v4l: vsp1: Don't create HGO entity when the userspace API is disabled
  2016-08-17 12:20 [PATCH v2 0/4] R-Car VSP1 1-D Histogram support Laurent Pinchart
                   ` (2 preceding siblings ...)
  2016-08-17 12:20 ` [PATCH v2 3/4] v4l: vsp1: Add HGO support Laurent Pinchart
@ 2016-08-17 12:20 ` Laurent Pinchart
  2016-09-05  8:08 ` [PATCH v2.2 1/4] v4l: Add metadata buffer type and format Laurent Pinchart
  2016-09-13 12:19 ` [PATCH v2 0/4] R-Car VSP1 1-D Histogram support Geert Uytterhoeven
  5 siblings, 0 replies; 17+ messages in thread
From: Laurent Pinchart @ 2016-08-17 12:20 UTC (permalink / raw)
  To: linux-media
  Cc: linux-renesas-soc, Sakari Ailus, Hans Verkuil, Guennadi Liakhovetski

The HGO is never used in the DRM pipeline, there is thus no need to
create an HGO entity when the userspace API is disabled.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/vsp1_drv.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
index 327066c25144..9684abf3ce3a 100644
--- a/drivers/media/platform/vsp1/vsp1_drv.c
+++ b/drivers/media/platform/vsp1/vsp1_drv.c
@@ -290,7 +290,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
 
 	list_add_tail(&vsp1->hst->entity.list_dev, &vsp1->entities);
 
-	if (vsp1->info->features & VSP1_HAS_HGO) {
+	if (vsp1->info->features & VSP1_HAS_HGO && vsp1->info->uapi) {
 		vsp1->hgo = vsp1_hgo_create(vsp1);
 		if (IS_ERR(vsp1->hgo)) {
 			ret = PTR_ERR(vsp1->hgo);
-- 
Regards,

Laurent Pinchart


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH v2 1/4] v4l: Add metadata buffer type and format
  2016-08-17 12:20 ` [PATCH v2 1/4] v4l: Add metadata buffer type and format Laurent Pinchart
@ 2016-08-29  9:13   ` Sakari Ailus
  2016-09-01 21:22     ` Laurent Pinchart
  0 siblings, 1 reply; 17+ messages in thread
From: Sakari Ailus @ 2016-08-29  9:13 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-media, linux-renesas-soc, Hans Verkuil, Guennadi Liakhovetski

Hi Laurent,

Thanks for the patchset!

On Wed, Aug 17, 2016 at 03:20:27PM +0300, Laurent Pinchart wrote:
> The metadata buffer type is used to transfer metadata between userspace
> and kernelspace through a V4L2 buffers queue. It comes with a new
> metadata capture capability and format description.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> Tested-by: Guennadi Liakhovetski <guennadi.liakhovetski@intel.com>
> ---
> Changes since v1:
> 
> - Rebased on top of the DocBook to reST conversion
> 
>  Documentation/media/uapi/v4l/buffer.rst          |  8 +++
>  Documentation/media/uapi/v4l/dev-meta.rst        | 69 ++++++++++++++++++++++++
>  Documentation/media/uapi/v4l/devices.rst         |  1 +
>  Documentation/media/uapi/v4l/vidioc-querycap.rst | 14 +++--
>  Documentation/media/videodev2.h.rst.exceptions   |  2 +
>  drivers/media/v4l2-core/v4l2-compat-ioctl32.c    | 19 +++++++
>  drivers/media/v4l2-core/v4l2-dev.c               | 16 +++---
>  drivers/media/v4l2-core/v4l2-ioctl.c             | 41 ++++++++++++++
>  drivers/media/v4l2-core/videobuf2-v4l2.c         |  3 ++
>  include/media/v4l2-ioctl.h                       | 17 ++++++
>  include/uapi/linux/videodev2.h                   | 14 +++++
>  11 files changed, 195 insertions(+), 9 deletions(-)
>  create mode 100644 Documentation/media/uapi/v4l/dev-meta.rst
> 
> diff --git a/Documentation/media/uapi/v4l/buffer.rst b/Documentation/media/uapi/v4l/buffer.rst
> index 5deb4a46f992..b5177cc63b86 100644
> --- a/Documentation/media/uapi/v4l/buffer.rst
> +++ b/Documentation/media/uapi/v4l/buffer.rst
> @@ -499,6 +499,14 @@ enum v4l2_buf_type
>         -  Buffer for Software Defined Radio (SDR) output stream, see
>  	  :ref:`sdr`.
>  
> +    -  .. row 13
> +
> +       -  ``V4L2_BUF_TYPE_META_CAPTURE``
> +
> +       -  13
> +
> +       -  Buffer for metadata capture, see :ref:`metadata`.
> +
>  
>  
>  .. _buffer-flags:
> diff --git a/Documentation/media/uapi/v4l/dev-meta.rst b/Documentation/media/uapi/v4l/dev-meta.rst
> new file mode 100644
> index 000000000000..252ed05b4841
> --- /dev/null
> +++ b/Documentation/media/uapi/v4l/dev-meta.rst
> @@ -0,0 +1,69 @@
> +.. -*- coding: utf-8; mode: rst -*-
> +
> +.. _metadata:
> +
> +******************
> +Metadata Interface
> +******************
> +
> +Metadata refers to any non-image data that supplements video frames with
> +additional information. This may include statistics computed over the image
> +or frame capture parameters supplied by the image source. This interface is
> +intended for transfer of metadata to userspace and control of that operation.
> +
> +The metadata interface is implemented on video capture device nodes. The device
> +can be dedicated to metadata or can implement both video and metadata capture
> +as specified in its reported capabilities.
> +
> +.. note::
> +
> +    This is an :ref:`experimental` interface and may
> +    change in the future.
> +
> +Querying Capabilities
> +=====================
> +
> +Device nodes supporting the metadata interface set the ``V4L2_CAP_META_CAPTURE``
> +flag in the ``device_caps`` field of the
> +:ref:`v4l2_capability <v4l2-capability>` structure returned by the
> +:ref:`VIDIOC_QUERYCAP` ioctl. That flag means the device can capture
> +metadata to memory.
> +
> +At least one of the read/write or streaming I/O methods must be supported.
> +
> +
> +Data Format Negotiation
> +=======================
> +
> +The metadata device uses the :ref:`format` ioctls to select the capture format.
> +The metadata buffer content format is bound to that selected format. In addition
> +to the basic :ref:`format` ioctls, the :ref:`VIDIOC_ENUM_FMT` ioctl must be
> +supported as well.
> +
> +To use the :ref:`format` ioctls applications set the ``type`` of the
> +:ref:`v4l2_format <v4l2-format>` structure to ``V4L2_BUF_TYPE_META_CAPTURE``
> +and use the :ref:`v4l2_meta_format <v4l2-meta-format>` ``meta`` member of the
> +``fmt`` union as needed per the desired operation. The :ref:`v4l2-meta-format`
> +structure contains two fields, ``dataformat`` is set by applications to the V4L2

I might not specify the number of number of fields here. It has high chances
of not getting updated when more fields are added. Up to you.

> +FourCC code of the desired format, and ``buffersize`` set by drivers to the
> +maximum buffer size (in bytes) required for data transfer.
> +
> +.. _v4l2-meta-format:
> +.. flat-table:: struct v4l2_meta_format
> +    :header-rows:  0
> +    :stub-columns: 0
> +    :widths:       1 1 2
> +
> +    * - __u32
> +      - ``dataformat``
> +      - The data format, set by the application. This is a little endian
> +        :ref:`four character code <v4l2-fourcc>`. V4L2 defines metadata formats
> +        in :ref:`meta-formats`.
> +    * - __u32
> +      - ``buffersize``
> +      - Maximum buffer size in bytes required for data. The value is set by the
> +        driver.

We'll need to add width and heigth as well but it could be done later on.

> +    * - __u8
> +      - ``reserved[24]``
> +      - This array is reserved for future extensions. Drivers and applications
> +        must set it to zero.

struct v4l2_pix_format has grown without use of reserved fields and it's
been around for ages.

It's not directly used in an IOCTL but within an union in another struct so
this is possible. I would consider doing the same here. Or at least
increasing the number of reserved fields (and possibly making the type u32)
if you feel we shouldn't go that way.

> diff --git a/Documentation/media/uapi/v4l/devices.rst b/Documentation/media/uapi/v4l/devices.rst
> index aed0ce11d1f8..961e7fb62063 100644
> --- a/Documentation/media/uapi/v4l/devices.rst
> +++ b/Documentation/media/uapi/v4l/devices.rst
> @@ -24,3 +24,4 @@ Interfaces
>      dev-sdr
>      dev-event
>      dev-subdev
> +    dev-meta
> diff --git a/Documentation/media/uapi/v4l/vidioc-querycap.rst b/Documentation/media/uapi/v4l/vidioc-querycap.rst
> index b10fed313f99..734fae6fc5e4 100644
> --- a/Documentation/media/uapi/v4l/vidioc-querycap.rst
> +++ b/Documentation/media/uapi/v4l/vidioc-querycap.rst
> @@ -387,6 +387,14 @@ specification the ioctl returns an ``EINVAL`` error code.
>  
>      -  .. row 23
>  
> +       -  ``V4L2_CAP_META_CAPTURE``
> +
> +       -  0x00800000
> +
> +       -  The device supports the :ref:`metadata` capture interface.
> +
> +    -  .. row 24
> +
>         -  ``V4L2_CAP_READWRITE``
>  
>         -  0x01000000
> @@ -394,7 +402,7 @@ specification the ioctl returns an ``EINVAL`` error code.
>         -  The device supports the :ref:`read() <rw>` and/or
>  	  :ref:`write() <rw>` I/O methods.
>  
> -    -  .. row 24
> +    -  .. row 25
>  
>         -  ``V4L2_CAP_ASYNCIO``
>  
> @@ -402,7 +410,7 @@ specification the ioctl returns an ``EINVAL`` error code.
>  
>         -  The device supports the :ref:`asynchronous <async>` I/O methods.
>  
> -    -  .. row 25
> +    -  .. row 26
>  
>         -  ``V4L2_CAP_STREAMING``
>  
> @@ -410,7 +418,7 @@ specification the ioctl returns an ``EINVAL`` error code.
>  
>         -  The device supports the :ref:`streaming <mmap>` I/O method.
>  
> -    -  .. row 26
> +    -  .. row 27
>  
>         -  ``V4L2_CAP_DEVICE_CAPS``
>  
> diff --git a/Documentation/media/videodev2.h.rst.exceptions b/Documentation/media/videodev2.h.rst.exceptions
> index 9bb9a6cc39d8..d1275725d367 100644
> --- a/Documentation/media/videodev2.h.rst.exceptions
> +++ b/Documentation/media/videodev2.h.rst.exceptions
> @@ -27,6 +27,7 @@ replace symbol V4L2_FIELD_SEQ_TB v4l2-field
>  replace symbol V4L2_FIELD_TOP v4l2-field
>  
>  # Documented enum v4l2_buf_type
> +replace symbol V4L2_BUF_TYPE_META_CAPTURE v4l2-buf-type
>  replace symbol V4L2_BUF_TYPE_SDR_CAPTURE v4l2-buf-type
>  replace symbol V4L2_BUF_TYPE_SDR_OUTPUT v4l2-buf-type
>  replace symbol V4L2_BUF_TYPE_SLICED_VBI_CAPTURE v4l2-buf-type
> @@ -148,6 +149,7 @@ replace define V4L2_CAP_MODULATOR device-capabilities
>  replace define V4L2_CAP_SDR_CAPTURE device-capabilities
>  replace define V4L2_CAP_EXT_PIX_FORMAT device-capabilities
>  replace define V4L2_CAP_SDR_OUTPUT device-capabilities
> +replace define V4L2_CAP_META_CAPTURE device-capabilities
>  replace define V4L2_CAP_READWRITE device-capabilities
>  replace define V4L2_CAP_ASYNCIO device-capabilities
>  replace define V4L2_CAP_STREAMING device-capabilities
> diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
> index bacecbd68a6d..da2d836e8887 100644
> --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
> +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
> @@ -161,6 +161,20 @@ static inline int put_v4l2_sdr_format(struct v4l2_sdr_format *kp, struct v4l2_sd
>  	return 0;
>  }
>  
> +static inline int get_v4l2_meta_format(struct v4l2_meta_format *kp, struct v4l2_meta_format __user *up)
> +{
> +	if (copy_from_user(kp, up, sizeof(struct v4l2_meta_format)))
> +		return -EFAULT;
> +	return 0;
> +}
> +
> +static inline int put_v4l2_meta_format(struct v4l2_meta_format *kp, struct v4l2_meta_format __user *up)
> +{
> +	if (copy_to_user(up, kp, sizeof(struct v4l2_meta_format)))
> +		return -EFAULT;
> +	return 0;
> +}
> +
>  struct v4l2_format32 {
>  	__u32	type;	/* enum v4l2_buf_type */
>  	union {
> @@ -170,6 +184,7 @@ struct v4l2_format32 {
>  		struct v4l2_vbi_format	vbi;
>  		struct v4l2_sliced_vbi_format	sliced;
>  		struct v4l2_sdr_format	sdr;
> +		struct v4l2_meta_format	meta;
>  		__u8	raw_data[200];        /* user-defined */
>  	} fmt;
>  };
> @@ -216,6 +231,8 @@ static int __get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __us
>  	case V4L2_BUF_TYPE_SDR_CAPTURE:
>  	case V4L2_BUF_TYPE_SDR_OUTPUT:
>  		return get_v4l2_sdr_format(&kp->fmt.sdr, &up->fmt.sdr);
> +	case V4L2_BUF_TYPE_META_CAPTURE:
> +		return get_v4l2_meta_format(&kp->fmt.meta, &up->fmt.meta);
>  	default:
>  		pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
>  								kp->type);
> @@ -263,6 +280,8 @@ static int __put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __us
>  	case V4L2_BUF_TYPE_SDR_CAPTURE:
>  	case V4L2_BUF_TYPE_SDR_OUTPUT:
>  		return put_v4l2_sdr_format(&kp->fmt.sdr, &up->fmt.sdr);
> +	case V4L2_BUF_TYPE_META_CAPTURE:
> +		return put_v4l2_meta_format(&kp->fmt.meta, &up->fmt.meta);
>  	default:
>  		pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
>  								kp->type);
> diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
> index e6da353b39bc..70af31210cd3 100644
> --- a/drivers/media/v4l2-core/v4l2-dev.c
> +++ b/drivers/media/v4l2-core/v4l2-dev.c
> @@ -574,30 +574,34 @@ static void determine_valid_ioctls(struct video_device *vdev)
>  		set_bit(_IOC_NR(VIDIOC_ENUM_FREQ_BANDS), valid_ioctls);
>  
>  	if (is_vid) {
> -		/* video specific ioctls */
> +		/* video and metadata specific ioctls */
>  		if ((is_rx && (ops->vidioc_enum_fmt_vid_cap ||
>  			       ops->vidioc_enum_fmt_vid_cap_mplane ||
> -			       ops->vidioc_enum_fmt_vid_overlay)) ||
> +			       ops->vidioc_enum_fmt_vid_overlay ||
> +			       ops->vidioc_enum_fmt_meta_cap)) ||
>  		    (is_tx && (ops->vidioc_enum_fmt_vid_out ||
>  			       ops->vidioc_enum_fmt_vid_out_mplane)))
>  			set_bit(_IOC_NR(VIDIOC_ENUM_FMT), valid_ioctls);
>  		if ((is_rx && (ops->vidioc_g_fmt_vid_cap ||
>  			       ops->vidioc_g_fmt_vid_cap_mplane ||
> -			       ops->vidioc_g_fmt_vid_overlay)) ||
> +			       ops->vidioc_g_fmt_vid_overlay ||
> +			       ops->vidioc_g_fmt_meta_cap)) ||
>  		    (is_tx && (ops->vidioc_g_fmt_vid_out ||
>  			       ops->vidioc_g_fmt_vid_out_mplane ||
>  			       ops->vidioc_g_fmt_vid_out_overlay)))
>  			 set_bit(_IOC_NR(VIDIOC_G_FMT), valid_ioctls);
>  		if ((is_rx && (ops->vidioc_s_fmt_vid_cap ||
>  			       ops->vidioc_s_fmt_vid_cap_mplane ||
> -			       ops->vidioc_s_fmt_vid_overlay)) ||
> +			       ops->vidioc_s_fmt_vid_overlay ||
> +			       ops->vidioc_s_fmt_meta_cap)) ||
>  		    (is_tx && (ops->vidioc_s_fmt_vid_out ||
>  			       ops->vidioc_s_fmt_vid_out_mplane ||
>  			       ops->vidioc_s_fmt_vid_out_overlay)))
>  			 set_bit(_IOC_NR(VIDIOC_S_FMT), valid_ioctls);
>  		if ((is_rx && (ops->vidioc_try_fmt_vid_cap ||
>  			       ops->vidioc_try_fmt_vid_cap_mplane ||
> -			       ops->vidioc_try_fmt_vid_overlay)) ||
> +			       ops->vidioc_try_fmt_vid_overlay ||
> +			       ops->vidioc_try_fmt_meta_cap)) ||
>  		    (is_tx && (ops->vidioc_try_fmt_vid_out ||
>  			       ops->vidioc_try_fmt_vid_out_mplane ||
>  			       ops->vidioc_try_fmt_vid_out_overlay)))
> @@ -663,7 +667,7 @@ static void determine_valid_ioctls(struct video_device *vdev)
>  	}
>  
>  	if (is_vid || is_vbi || is_sdr) {
> -		/* ioctls valid for video, vbi or sdr */
> +		/* ioctls valid for video, metadata, vbi or sdr */
>  		SET_VALID_IOCTL(ops, VIDIOC_REQBUFS, vidioc_reqbufs);
>  		SET_VALID_IOCTL(ops, VIDIOC_QUERYBUF, vidioc_querybuf);
>  		SET_VALID_IOCTL(ops, VIDIOC_QBUF, vidioc_qbuf);
> diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
> index 51a0fa144392..0afa07bfea35 100644
> --- a/drivers/media/v4l2-core/v4l2-ioctl.c
> +++ b/drivers/media/v4l2-core/v4l2-ioctl.c
> @@ -37,6 +37,13 @@
>  	memset((u8 *)(p) + offsetof(typeof(*(p)), field) + sizeof((p)->field), \
>  	0, sizeof(*(p)) - offsetof(typeof(*(p)), field) - sizeof((p)->field))
>  
> +/* Zero out the end of the struct pointed to by p.  Everything including and
> + * after thee specified field is cleared.
> + */
> +#define CLEAR_FROM_FIELD(p, field) \
> +	memset((u8 *)(p) + offsetof(typeof(*(p)), field), \
> +	0, sizeof(*(p)) - offsetof(typeof(*(p)), field))
> +
>  #define is_valid_ioctl(vfd, cmd) test_bit(_IOC_NR(cmd), (vfd)->valid_ioctls)
>  
>  struct std_descr {
> @@ -155,6 +162,7 @@ const char *v4l2_type_names[] = {
>  	[V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE] = "vid-out-mplane",
>  	[V4L2_BUF_TYPE_SDR_CAPTURE]        = "sdr-cap",
>  	[V4L2_BUF_TYPE_SDR_OUTPUT]         = "sdr-out",
> +	[V4L2_BUF_TYPE_META_CAPTURE]       = "meta-cap",
>  };
>  EXPORT_SYMBOL(v4l2_type_names);
>  
> @@ -249,6 +257,7 @@ static void v4l_print_format(const void *arg, bool write_only)
>  	const struct v4l2_sliced_vbi_format *sliced;
>  	const struct v4l2_window *win;
>  	const struct v4l2_sdr_format *sdr;
> +	const struct v4l2_meta_format *meta;
>  	unsigned i;
>  
>  	pr_cont("type=%s", prt_names(p->type, v4l2_type_names));
> @@ -336,6 +345,15 @@ static void v4l_print_format(const void *arg, bool write_only)
>  			(sdr->pixelformat >> 16) & 0xff,
>  			(sdr->pixelformat >> 24) & 0xff);
>  		break;
> +	case V4L2_BUF_TYPE_META_CAPTURE:
> +		meta = &p->fmt.meta;
> +		pr_cont(", dataformat=%c%c%c%c, buffersize=%u\n",
> +			(meta->dataformat >>  0) & 0xff,
> +			(meta->dataformat >>  8) & 0xff,
> +			(meta->dataformat >> 16) & 0xff,
> +			(meta->dataformat >> 24) & 0xff,
> +			meta->buffersize);
> +		break;
>  	}
>  }
>  
> @@ -981,6 +999,10 @@ static int check_fmt(struct file *file, enum v4l2_buf_type type)
>  		if (is_sdr && is_tx && ops->vidioc_g_fmt_sdr_out)
>  			return 0;
>  		break;
> +	case V4L2_BUF_TYPE_META_CAPTURE:
> +		if (is_vid && is_rx && ops->vidioc_g_fmt_meta_cap)
> +			return 0;
> +		break;
>  	default:
>  		break;
>  	}
> @@ -1349,6 +1371,11 @@ static int v4l_enum_fmt(const struct v4l2_ioctl_ops *ops,
>  			break;
>  		ret = ops->vidioc_enum_fmt_sdr_out(file, fh, arg);
>  		break;
> +	case V4L2_BUF_TYPE_META_CAPTURE:
> +		if (unlikely(!is_rx || !is_vid || !ops->vidioc_enum_fmt_meta_cap))
> +			break;
> +		ret = ops->vidioc_enum_fmt_meta_cap(file, fh, arg);
> +		break;
>  	}
>  	if (ret == 0)
>  		v4l_fill_fmtdesc(p);
> @@ -1447,6 +1474,10 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops,
>  		if (unlikely(!is_tx || !is_sdr || !ops->vidioc_g_fmt_sdr_out))
>  			break;
>  		return ops->vidioc_g_fmt_sdr_out(file, fh, arg);
> +	case V4L2_BUF_TYPE_META_CAPTURE:
> +		if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_meta_cap))
> +			break;
> +		return ops->vidioc_g_fmt_meta_cap(file, fh, arg);
>  	}
>  	return -EINVAL;
>  }
> @@ -1534,6 +1565,11 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,
>  			break;
>  		CLEAR_AFTER_FIELD(p, fmt.sdr);
>  		return ops->vidioc_s_fmt_sdr_out(file, fh, arg);
> +	case V4L2_BUF_TYPE_META_CAPTURE:
> +		if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_meta_cap))
> +			break;
> +		CLEAR_FROM_FIELD(p, fmt.meta.reserved);
> +		return ops->vidioc_s_fmt_meta_cap(file, fh, arg);
>  	}
>  	return -EINVAL;
>  }
> @@ -1618,6 +1654,11 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops,
>  			break;
>  		CLEAR_AFTER_FIELD(p, fmt.sdr);
>  		return ops->vidioc_try_fmt_sdr_out(file, fh, arg);
> +	case V4L2_BUF_TYPE_META_CAPTURE:
> +		if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_meta_cap))
> +			break;
> +		CLEAR_FROM_FIELD(p, fmt.meta.reserved);
> +		return ops->vidioc_try_fmt_meta_cap(file, fh, arg);
>  	}
>  	return -EINVAL;
>  }
> diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c
> index 9cfbb6e4bc28..7216668d1056 100644
> --- a/drivers/media/v4l2-core/videobuf2-v4l2.c
> +++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
> @@ -575,6 +575,9 @@ int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
>  	case V4L2_BUF_TYPE_SDR_OUTPUT:
>  		requested_sizes[0] = f->fmt.sdr.buffersize;
>  		break;
> +	case V4L2_BUF_TYPE_META_CAPTURE:
> +		requested_sizes[0] = f->fmt.meta.buffersize;
> +		break;
>  	default:
>  		return -EINVAL;
>  	}
> diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
> index 8b1d19bc9b0e..a32dcf78d4a3 100644
> --- a/include/media/v4l2-ioctl.h
> +++ b/include/media/v4l2-ioctl.h
> @@ -43,6 +43,9 @@ struct v4l2_fh;
>   * @vidioc_enum_fmt_sdr_out: pointer to the function that implements
>   *	:ref:`VIDIOC_ENUM_FMT <vidioc_enum_fmt>` ioctl logic
>   *	for Software Defined Radio output
> + * @vidioc_enum_fmt_meta_cap: pointer to the function that implements
> + *	:ref:`VIDIOC_ENUM_FMT <vidioc_enum_fmt>` ioctl logic
> + *	for metadata capture
>   * @vidioc_g_fmt_vid_cap: pointer to the function that implements
>   *	:ref:`VIDIOC_G_FMT <vidioc_g_fmt>` ioctl logic for video capture
>   *	in single plane mode
> @@ -73,6 +76,8 @@ struct v4l2_fh;
>   * @vidioc_g_fmt_sdr_out: pointer to the function that implements
>   *	:ref:`VIDIOC_G_FMT <vidioc_g_fmt>` ioctl logic for Software Defined
>   *	Radio output
> + * @vidioc_g_fmt_meta_cap: pointer to the function that implements
> + *	:ref:`VIDIOC_G_FMT <vidioc_g_fmt>` ioctl logic for metadata capture
>   * @vidioc_s_fmt_vid_cap: pointer to the function that implements
>   *	:ref:`VIDIOC_S_FMT <vidioc_g_fmt>` ioctl logic for video capture
>   *	in single plane mode
> @@ -103,6 +108,8 @@ struct v4l2_fh;
>   * @vidioc_s_fmt_sdr_out: pointer to the function that implements
>   *	:ref:`VIDIOC_S_FMT <vidioc_g_fmt>` ioctl logic for Software Defined
>   *	Radio output
> + * @vidioc_s_fmt_meta_cap: pointer to the function that implements
> + *	:ref:`VIDIOC_S_FMT <vidioc_g_fmt>` ioctl logic for metadata capture
>   * @vidioc_try_fmt_vid_cap: pointer to the function that implements
>   *	:ref:`VIDIOC_TRY_FMT <vidioc_g_fmt>` ioctl logic for video capture
>   *	in single plane mode
> @@ -135,6 +142,8 @@ struct v4l2_fh;
>   * @vidioc_try_fmt_sdr_out: pointer to the function that implements
>   *	:ref:`VIDIOC_TRY_FMT <vidioc_g_fmt>` ioctl logic for Software Defined
>   *	Radio output
> + * @vidioc_try_fmt_meta_cap: pointer to the function that implements
> + *	:ref:`VIDIOC_TRY_FMT <vidioc_g_fmt>` ioctl logic for metadata capture
>   * @vidioc_reqbufs: pointer to the function that implements
>   *	:ref:`VIDIOC_REQBUFS <vidioc_reqbufs>` ioctl
>   * @vidioc_querybuf: pointer to the function that implements
> @@ -304,6 +313,8 @@ struct v4l2_ioctl_ops {
>  					    struct v4l2_fmtdesc *f);
>  	int (*vidioc_enum_fmt_sdr_out)     (struct file *file, void *fh,
>  					    struct v4l2_fmtdesc *f);
> +	int (*vidioc_enum_fmt_meta_cap)    (struct file *file, void *fh,
> +					    struct v4l2_fmtdesc *f);
>  
>  	/* VIDIOC_G_FMT handlers */
>  	int (*vidioc_g_fmt_vid_cap)    (struct file *file, void *fh,
> @@ -330,6 +341,8 @@ struct v4l2_ioctl_ops {
>  					struct v4l2_format *f);
>  	int (*vidioc_g_fmt_sdr_out)    (struct file *file, void *fh,
>  					struct v4l2_format *f);
> +	int (*vidioc_g_fmt_meta_cap)   (struct file *file, void *fh,
> +					struct v4l2_format *f);
>  
>  	/* VIDIOC_S_FMT handlers */
>  	int (*vidioc_s_fmt_vid_cap)    (struct file *file, void *fh,
> @@ -356,6 +369,8 @@ struct v4l2_ioctl_ops {
>  					struct v4l2_format *f);
>  	int (*vidioc_s_fmt_sdr_out)    (struct file *file, void *fh,
>  					struct v4l2_format *f);
> +	int (*vidioc_s_fmt_meta_cap)   (struct file *file, void *fh,
> +					struct v4l2_format *f);
>  
>  	/* VIDIOC_TRY_FMT handlers */
>  	int (*vidioc_try_fmt_vid_cap)    (struct file *file, void *fh,
> @@ -382,6 +397,8 @@ struct v4l2_ioctl_ops {
>  					  struct v4l2_format *f);
>  	int (*vidioc_try_fmt_sdr_out)    (struct file *file, void *fh,
>  					  struct v4l2_format *f);
> +	int (*vidioc_try_fmt_meta_cap)   (struct file *file, void *fh,
> +					  struct v4l2_format *f);
>  
>  	/* Buffer handlers */
>  	int (*vidioc_reqbufs) (struct file *file, void *fh, struct v4l2_requestbuffers *b);
> diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
> index 724f43e69d03..d1ac0250a966 100644
> --- a/include/uapi/linux/videodev2.h
> +++ b/include/uapi/linux/videodev2.h
> @@ -143,6 +143,7 @@ enum v4l2_buf_type {
>  	V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE  = 10,
>  	V4L2_BUF_TYPE_SDR_CAPTURE          = 11,
>  	V4L2_BUF_TYPE_SDR_OUTPUT           = 12,
> +	V4L2_BUF_TYPE_META_CAPTURE         = 13,
>  	/* Deprecated, do not use */
>  	V4L2_BUF_TYPE_PRIVATE              = 0x80,
>  };
> @@ -435,6 +436,7 @@ struct v4l2_capability {
>  #define V4L2_CAP_SDR_CAPTURE		0x00100000  /* Is a SDR capture device */
>  #define V4L2_CAP_EXT_PIX_FORMAT		0x00200000  /* Supports the extended pixel format */
>  #define V4L2_CAP_SDR_OUTPUT		0x00400000  /* Is a SDR output device */
> +#define V4L2_CAP_META_CAPTURE		0x00800000  /* Is a metadata capture device */
>  
>  #define V4L2_CAP_READWRITE              0x01000000  /* read/write systemcalls */
>  #define V4L2_CAP_ASYNCIO                0x02000000  /* async I/O */
> @@ -2002,6 +2004,17 @@ struct v4l2_sdr_format {
>  } __attribute__ ((packed));
>  
>  /**
> + * struct v4l2_meta_format - metadata format definition
> + * @dataformat:		little endian four character code (fourcc)
> + * @buffersize:		maximum size in bytes required for data
> + */
> +struct v4l2_meta_format {
> +	__u32				dataformat;
> +	__u32				buffersize;
> +	__u8				reserved[24];
> +} __attribute__ ((packed));
> +
> +/**
>   * struct v4l2_format - stream data format
>   * @type:	enum v4l2_buf_type; type of the data stream
>   * @pix:	definition of an image format
> @@ -2020,6 +2033,7 @@ struct v4l2_format {
>  		struct v4l2_vbi_format		vbi;     /* V4L2_BUF_TYPE_VBI_CAPTURE */
>  		struct v4l2_sliced_vbi_format	sliced;  /* V4L2_BUF_TYPE_SLICED_VBI_CAPTURE */
>  		struct v4l2_sdr_format		sdr;     /* V4L2_BUF_TYPE_SDR_CAPTURE */
> +		struct v4l2_meta_format		meta;    /* V4L2_BUF_TYPE_META_CAPTURE */
>  		__u8	raw_data[200];                   /* user-defined */
>  	} fmt;
>  };

-- 
Kind regards,

Sakari Ailus
e-mail: sakari.ailus@iki.fi	XMPP: sailus@retiisi.org.uk

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v2 1/4] v4l: Add metadata buffer type and format
  2016-08-29  9:13   ` Sakari Ailus
@ 2016-09-01 21:22     ` Laurent Pinchart
  2016-09-01 21:40       ` Laurent Pinchart
  2016-09-02  7:31       ` Sakari Ailus
  0 siblings, 2 replies; 17+ messages in thread
From: Laurent Pinchart @ 2016-09-01 21:22 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: Laurent Pinchart, linux-media, linux-renesas-soc, Hans Verkuil,
	Guennadi Liakhovetski

Hi Sakari,

On Monday 29 Aug 2016 12:13:40 Sakari Ailus wrote:
> On Wed, Aug 17, 2016 at 03:20:27PM +0300, Laurent Pinchart wrote:
> > The metadata buffer type is used to transfer metadata between userspace
> > and kernelspace through a V4L2 buffers queue. It comes with a new
> > metadata capture capability and format description.
> > 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> > Tested-by: Guennadi Liakhovetski <guennadi.liakhovetski@intel.com>
> > ---
> > Changes since v1:
> > 
> > - Rebased on top of the DocBook to reST conversion
> > 
> >  Documentation/media/uapi/v4l/buffer.rst          |  8 +++
> >  Documentation/media/uapi/v4l/dev-meta.rst        | 69 +++++++++++++++++++
> >  Documentation/media/uapi/v4l/devices.rst         |  1 +
> >  Documentation/media/uapi/v4l/vidioc-querycap.rst | 14 +++--
> >  Documentation/media/videodev2.h.rst.exceptions   |  2 +
> >  drivers/media/v4l2-core/v4l2-compat-ioctl32.c    | 19 +++++++
> >  drivers/media/v4l2-core/v4l2-dev.c               | 16 +++---
> >  drivers/media/v4l2-core/v4l2-ioctl.c             | 41 ++++++++++++++
> >  drivers/media/v4l2-core/videobuf2-v4l2.c         |  3 ++
> >  include/media/v4l2-ioctl.h                       | 17 ++++++
> >  include/uapi/linux/videodev2.h                   | 14 +++++
> >  11 files changed, 195 insertions(+), 9 deletions(-)
> >  create mode 100644 Documentation/media/uapi/v4l/dev-meta.rst

[snip]

> > diff --git a/Documentation/media/uapi/v4l/dev-meta.rst
> > b/Documentation/media/uapi/v4l/dev-meta.rst new file mode 100644
> > index 000000000000..252ed05b4841
> > --- /dev/null
> > +++ b/Documentation/media/uapi/v4l/dev-meta.rst
> > @@ -0,0 +1,69 @@
> > +.. -*- coding: utf-8; mode: rst -*-
> > +
> > +.. _metadata:
> > +
> > +******************
> > +Metadata Interface
> > +******************
> > +
> > +Metadata refers to any non-image data that supplements video frames with
> > +additional information. This may include statistics computed over the
> > image +or frame capture parameters supplied by the image source. This
> > interface is +intended for transfer of metadata to userspace and control
> > of that operation. +
> > +The metadata interface is implemented on video capture device nodes. The
> > device +can be dedicated to metadata or can implement both video and
> > metadata capture +as specified in its reported capabilities.
> > +
> > +.. note::
> > +
> > +    This is an :ref:`experimental` interface and may
> > +    change in the future.
> > +
> > +Querying Capabilities
> > +=====================
> > +
> > +Device nodes supporting the metadata interface set the
> > ``V4L2_CAP_META_CAPTURE`` +flag in the ``device_caps`` field of the
> > +:ref:`v4l2_capability <v4l2-capability>` structure returned by the
> > +:ref:`VIDIOC_QUERYCAP` ioctl. That flag means the device can capture
> > +metadata to memory.
> > +
> > +At least one of the read/write or streaming I/O methods must be
> > supported.
> > +
> > +
> > +Data Format Negotiation
> > +=======================
> > +
> > +The metadata device uses the :ref:`format` ioctls to select the capture
> > format. +The metadata buffer content format is bound to that selected
> > format. In addition +to the basic :ref:`format` ioctls, the
> > :ref:`VIDIOC_ENUM_FMT` ioctl must be +supported as well.
> > +
> > +To use the :ref:`format` ioctls applications set the ``type`` of the
> > +:ref:`v4l2_format <v4l2-format>` structure to
> > ``V4L2_BUF_TYPE_META_CAPTURE`` +and use the :ref:`v4l2_meta_format
> > <v4l2-meta-format>` ``meta`` member of the +``fmt`` union as needed per
> > the desired operation. The :ref:`v4l2-meta-format` +structure contains
> > two fields, ``dataformat`` is set by applications to the V4L2
>
> I might not specify the number of number of fields here. It has high chances
> of not getting updated when more fields are added. Up to you.

This has been copied from dev-sdr.rst. I can drop the last sentence completely 
as the parameters are described in the table below. Hans, any opinion ?

> > +FourCC code of the desired format, and ``buffersize`` set by drivers to
> > the +maximum buffer size (in bytes) required for data transfer.
> > +
> > +.. _v4l2-meta-format:
> > +.. flat-table:: struct v4l2_meta_format
> > +    :header-rows:  0
> > +    :stub-columns: 0
> > +    :widths:       1 1 2
> > +
> > +    * - __u32
> > +      - ``dataformat``
> > +      - The data format, set by the application. This is a little endian
> > +        :ref:`four character code <v4l2-fourcc>`. V4L2 defines metadata
> > formats +        in :ref:`meta-formats`.
> > +    * - __u32
> > +      - ``buffersize``
> > +      - Maximum buffer size in bytes required for data. The value is set
> > by the +        driver.
> 
> We'll need to add width and heigth as well but it could be done later on.

Unless you have a use case you can upstream now for those fields we'll have to 
add them later.

> > +    * - __u8
> > +      - ``reserved[24]``
> > +      - This array is reserved for future extensions. Drivers and
> > applications +        must set it to zero.
> 
> struct v4l2_pix_format has grown without use of reserved fields and it's
> been around for ages.
> 
> It's not directly used in an IOCTL but within an union in another struct so
> this is possible. I would consider doing the same here. Or at least
> increasing the number of reserved fields (and possibly making the type u32)
> if you feel we shouldn't go that way.

I'm fine with dropping the reserved fields.

-- 
Regards,

Laurent Pinchart


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v2 1/4] v4l: Add metadata buffer type and format
  2016-09-01 21:22     ` Laurent Pinchart
@ 2016-09-01 21:40       ` Laurent Pinchart
  2016-09-02  8:18         ` Sakari Ailus
  2016-09-02  7:31       ` Sakari Ailus
  1 sibling, 1 reply; 17+ messages in thread
From: Laurent Pinchart @ 2016-09-01 21:40 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: Laurent Pinchart, linux-media, linux-renesas-soc, Hans Verkuil,
	Guennadi Liakhovetski

On Friday 02 Sep 2016 00:22:42 Laurent Pinchart wrote:
> On Monday 29 Aug 2016 12:13:40 Sakari Ailus wrote:
> > On Wed, Aug 17, 2016 at 03:20:27PM +0300, Laurent Pinchart wrote:
> >> The metadata buffer type is used to transfer metadata between userspace
> >> and kernelspace through a V4L2 buffers queue. It comes with a new
> >> metadata capture capability and format description.
> >> 
> >> Signed-off-by: Laurent Pinchart
> >> <laurent.pinchart+renesas@ideasonboard.com>
> >> Tested-by: Guennadi Liakhovetski <guennadi.liakhovetski@intel.com>
> >> ---
> >> Changes since v1:
> >> 
> >> - Rebased on top of the DocBook to reST conversion
> >> 
> >>  Documentation/media/uapi/v4l/buffer.rst          |  8 +++
> >>  Documentation/media/uapi/v4l/dev-meta.rst        | 69 +++++++++++++++++
> >>  Documentation/media/uapi/v4l/devices.rst         |  1 +
> >>  Documentation/media/uapi/v4l/vidioc-querycap.rst | 14 +++--
> >>  Documentation/media/videodev2.h.rst.exceptions   |  2 +
> >>  drivers/media/v4l2-core/v4l2-compat-ioctl32.c    | 19 +++++++
> >>  drivers/media/v4l2-core/v4l2-dev.c               | 16 +++---
> >>  drivers/media/v4l2-core/v4l2-ioctl.c             | 41 ++++++++++++++
> >>  drivers/media/v4l2-core/videobuf2-v4l2.c         |  3 ++
> >>  include/media/v4l2-ioctl.h                       | 17 ++++++
> >>  include/uapi/linux/videodev2.h                   | 14 +++++
> >>  11 files changed, 195 insertions(+), 9 deletions(-)
> >>  create mode 100644 Documentation/media/uapi/v4l/dev-meta.rst
> 
> [snip]
> 
> >> diff --git a/Documentation/media/uapi/v4l/dev-meta.rst
> >> b/Documentation/media/uapi/v4l/dev-meta.rst new file mode 100644
> >> index 000000000000..252ed05b4841
> >> --- /dev/null
> >> +++ b/Documentation/media/uapi/v4l/dev-meta.rst
> >> @@ -0,0 +1,69 @@
> >> +.. -*- coding: utf-8; mode: rst -*-
> >> +
> >> +.. _metadata:
> >> +
> >> +******************
> >> +Metadata Interface
> >> +******************
> >> +
> >> +Metadata refers to any non-image data that supplements video frames
> >> with
> >> +additional information. This may include statistics computed over the
> >> image +or frame capture parameters supplied by the image source. This
> >> interface is +intended for transfer of metadata to userspace and control
> >> of that operation. +
> >> +The metadata interface is implemented on video capture device nodes.
> >> The
> >> device +can be dedicated to metadata or can implement both video and
> >> metadata capture +as specified in its reported capabilities.
> >> +
> >> +.. note::
> >> +
> >> +    This is an :ref:`experimental` interface and may
> >> +    change in the future.
> >> +
> >> +Querying Capabilities
> >> +=====================
> >> +
> >> +Device nodes supporting the metadata interface set the
> >> ``V4L2_CAP_META_CAPTURE`` +flag in the ``device_caps`` field of the
> >> +:ref:`v4l2_capability <v4l2-capability>` structure returned by the
> >> +:ref:`VIDIOC_QUERYCAP` ioctl. That flag means the device can capture
> >> +metadata to memory.
> >> +
> >> +At least one of the read/write or streaming I/O methods must be
> >> supported.
> >> +
> >> +
> >> +Data Format Negotiation
> >> +=======================
> >> +
> >> +The metadata device uses the :ref:`format` ioctls to select the capture
> >> format. +The metadata buffer content format is bound to that selected
> >> format. In addition +to the basic :ref:`format` ioctls, the
> >> 
> >> :ref:`VIDIOC_ENUM_FMT` ioctl must be +supported as well.
> >> 
> >> +
> >> +To use the :ref:`format` ioctls applications set the ``type`` of the
> >> +:ref:`v4l2_format <v4l2-format>` structure to
> >> ``V4L2_BUF_TYPE_META_CAPTURE`` +and use the :ref:`v4l2_meta_format
> >> <v4l2-meta-format>` ``meta`` member of the +``fmt`` union as needed per
> >> the desired operation. The :ref:`v4l2-meta-format` +structure contains
> >> two fields, ``dataformat`` is set by applications to the V4L2
> > 
> > I might not specify the number of number of fields here. It has high
> > chances of not getting updated when more fields are added. Up to you.
> 
> This has been copied from dev-sdr.rst. I can drop the last sentence
> completely as the parameters are described in the table below. Hans, any
> opinion ?

How about this ?

To use the :ref:`format` ioctls applications set the ``type`` of the
:ref:`v4l2_format <v4l2-format>` structure to ``V4L2_BUF_TYPE_META_CAPTURE``
and use the :ref:`v4l2_meta_format <v4l2-meta-format>` ``meta`` member of the
``fmt`` union as needed per the desired operation. Both drivers and 
applications must set the remainder of the :ref:`v4l2_format <v4l2-format>` 
structure to 0.

> >> +FourCC code of the desired format, and ``buffersize`` set by drivers to
> >> the
> >> +maximum buffer size (in bytes) required for data transfer.
> >> +
> >> +.. _v4l2-meta-format:
> >> +.. flat-table:: struct v4l2_meta_format
> >> +    :header-rows:  0
> >> +    :stub-columns: 0
> >> +    :widths:       1 1 2
> >> +
> >> +    * - __u32
> >> +      - ``dataformat``
> >> +      - The data format, set by the application. This is a little
> >> endian
> >> +        :ref:`four character code <v4l2-fourcc>`. V4L2 defines metadata
> >> formats
> >> +        in :ref:`meta-formats`.
> >> +    * - __u32
> >> +      - ``buffersize``
> >> +      - Maximum buffer size in bytes required for data. The value is
> >> set by the
> >> +        driver.
> > 
> > We'll need to add width and heigth as well but it could be done later on.
> 
> Unless you have a use case you can upstream now for those fields we'll have
> to add them later.
> 
> >> +    * - __u8
> >> +      - ``reserved[24]``
> >> +      - This array is reserved for future extensions. Drivers and
> >> applications
> >> +        must set it to zero.
> > 
> > struct v4l2_pix_format has grown without use of reserved fields and it's
> > been around for ages.
> > 
> > It's not directly used in an IOCTL but within an union in another struct
> > so this is possible. I would consider doing the same here. Or at least
> > increasing the number of reserved fields (and possibly making the type
> > u32) if you feel we shouldn't go that way.
> 
> I'm fine with dropping the reserved fields.

-- 
Regards,

Laurent Pinchart


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v2 1/4] v4l: Add metadata buffer type and format
  2016-09-01 21:22     ` Laurent Pinchart
  2016-09-01 21:40       ` Laurent Pinchart
@ 2016-09-02  7:31       ` Sakari Ailus
  1 sibling, 0 replies; 17+ messages in thread
From: Sakari Ailus @ 2016-09-02  7:31 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Laurent Pinchart, linux-media, linux-renesas-soc, Hans Verkuil,
	Guennadi Liakhovetski

Huomenta!

On Fri, Sep 02, 2016 at 12:22:42AM +0300, Laurent Pinchart wrote:
> Hi Sakari,
> 
> On Monday 29 Aug 2016 12:13:40 Sakari Ailus wrote:
> > On Wed, Aug 17, 2016 at 03:20:27PM +0300, Laurent Pinchart wrote:
> > > The metadata buffer type is used to transfer metadata between userspace
> > > and kernelspace through a V4L2 buffers queue. It comes with a new
> > > metadata capture capability and format description.
> > > 
> > > Signed-off-by: Laurent Pinchart
> > > <laurent.pinchart+renesas@ideasonboard.com>
> > > Tested-by: Guennadi Liakhovetski <guennadi.liakhovetski@intel.com>
> > > ---
> > > Changes since v1:
> > > 
> > > - Rebased on top of the DocBook to reST conversion
> > > 
> > >  Documentation/media/uapi/v4l/buffer.rst          |  8 +++
> > >  Documentation/media/uapi/v4l/dev-meta.rst        | 69 +++++++++++++++++++
> > >  Documentation/media/uapi/v4l/devices.rst         |  1 +
> > >  Documentation/media/uapi/v4l/vidioc-querycap.rst | 14 +++--
> > >  Documentation/media/videodev2.h.rst.exceptions   |  2 +
> > >  drivers/media/v4l2-core/v4l2-compat-ioctl32.c    | 19 +++++++
> > >  drivers/media/v4l2-core/v4l2-dev.c               | 16 +++---
> > >  drivers/media/v4l2-core/v4l2-ioctl.c             | 41 ++++++++++++++
> > >  drivers/media/v4l2-core/videobuf2-v4l2.c         |  3 ++
> > >  include/media/v4l2-ioctl.h                       | 17 ++++++
> > >  include/uapi/linux/videodev2.h                   | 14 +++++
> > >  11 files changed, 195 insertions(+), 9 deletions(-)
> > >  create mode 100644 Documentation/media/uapi/v4l/dev-meta.rst
> 
> [snip]
> 
> > > diff --git a/Documentation/media/uapi/v4l/dev-meta.rst
> > > b/Documentation/media/uapi/v4l/dev-meta.rst new file mode 100644
> > > index 000000000000..252ed05b4841
> > > --- /dev/null
> > > +++ b/Documentation/media/uapi/v4l/dev-meta.rst
> > > @@ -0,0 +1,69 @@
> > > +.. -*- coding: utf-8; mode: rst -*-
> > > +
> > > +.. _metadata:
> > > +
> > > +******************
> > > +Metadata Interface
> > > +******************
> > > +
> > > +Metadata refers to any non-image data that supplements video frames with
> > > +additional information. This may include statistics computed over the
> > > image +or frame capture parameters supplied by the image source. This
> > > interface is +intended for transfer of metadata to userspace and control
> > > of that operation. +
> > > +The metadata interface is implemented on video capture device nodes. The
> > > device +can be dedicated to metadata or can implement both video and
> > > metadata capture +as specified in its reported capabilities.
> > > +
> > > +.. note::
> > > +
> > > +    This is an :ref:`experimental` interface and may
> > > +    change in the future.
> > > +
> > > +Querying Capabilities
> > > +=====================
> > > +
> > > +Device nodes supporting the metadata interface set the
> > > ``V4L2_CAP_META_CAPTURE`` +flag in the ``device_caps`` field of the
> > > +:ref:`v4l2_capability <v4l2-capability>` structure returned by the
> > > +:ref:`VIDIOC_QUERYCAP` ioctl. That flag means the device can capture
> > > +metadata to memory.
> > > +
> > > +At least one of the read/write or streaming I/O methods must be
> > > supported.
> > > +
> > > +
> > > +Data Format Negotiation
> > > +=======================
> > > +
> > > +The metadata device uses the :ref:`format` ioctls to select the capture
> > > format. +The metadata buffer content format is bound to that selected
> > > format. In addition +to the basic :ref:`format` ioctls, the
> > > :ref:`VIDIOC_ENUM_FMT` ioctl must be +supported as well.
> > > +
> > > +To use the :ref:`format` ioctls applications set the ``type`` of the
> > > +:ref:`v4l2_format <v4l2-format>` structure to
> > > ``V4L2_BUF_TYPE_META_CAPTURE`` +and use the :ref:`v4l2_meta_format
> > > <v4l2-meta-format>` ``meta`` member of the +``fmt`` union as needed per
> > > the desired operation. The :ref:`v4l2-meta-format` +structure contains
> > > two fields, ``dataformat`` is set by applications to the V4L2
> >
> > I might not specify the number of number of fields here. It has high chances
> > of not getting updated when more fields are added. Up to you.
> 
> This has been copied from dev-sdr.rst. I can drop the last sentence completely 
> as the parameters are described in the table below. Hans, any opinion ?
> 
> > > +FourCC code of the desired format, and ``buffersize`` set by drivers to
> > > the +maximum buffer size (in bytes) required for data transfer.
> > > +
> > > +.. _v4l2-meta-format:
> > > +.. flat-table:: struct v4l2_meta_format
> > > +    :header-rows:  0
> > > +    :stub-columns: 0
> > > +    :widths:       1 1 2
> > > +
> > > +    * - __u32
> > > +      - ``dataformat``
> > > +      - The data format, set by the application. This is a little endian
> > > +        :ref:`four character code <v4l2-fourcc>`. V4L2 defines metadata
> > > formats +        in :ref:`meta-formats`.
> > > +    * - __u32
> > > +      - ``buffersize``
> > > +      - Maximum buffer size in bytes required for data. The value is set
> > > by the +        driver.
> > 
> > We'll need to add width and heigth as well but it could be done later on.
> 
> Unless you have a use case you can upstream now for those fields we'll have to 
> add them later.

Later is fine. I just wanted to inform you they'll be needed.

> 
> > > +    * - __u8
> > > +      - ``reserved[24]``
> > > +      - This array is reserved for future extensions. Drivers and
> > > applications +        must set it to zero.
> > 
> > struct v4l2_pix_format has grown without use of reserved fields and it's
> > been around for ages.
> > 
> > It's not directly used in an IOCTL but within an union in another struct so
> > this is possible. I would consider doing the same here. Or at least
> > increasing the number of reserved fields (and possibly making the type u32)
> > if you feel we shouldn't go that way.
> 
> I'm fine with dropping the reserved fields.

Please. :-)

-- 
Terveisin,

Sakari Ailus
e-mail: sakari.ailus@iki.fi	XMPP: sailus@retiisi.org.uk

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v2 1/4] v4l: Add metadata buffer type and format
  2016-09-01 21:40       ` Laurent Pinchart
@ 2016-09-02  8:18         ` Sakari Ailus
  0 siblings, 0 replies; 17+ messages in thread
From: Sakari Ailus @ 2016-09-02  8:18 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Laurent Pinchart, linux-media, linux-renesas-soc, Hans Verkuil,
	Guennadi Liakhovetski

Hi Laurent,

On Fri, Sep 02, 2016 at 12:40:18AM +0300, Laurent Pinchart wrote:
...
> > >> +Data Format Negotiation
> > >> +=======================
> > >> +
> > >> +The metadata device uses the :ref:`format` ioctls to select the capture
> > >> format. +The metadata buffer content format is bound to that selected
> > >> format. In addition +to the basic :ref:`format` ioctls, the
> > >> 
> > >> :ref:`VIDIOC_ENUM_FMT` ioctl must be +supported as well.
> > >> 
> > >> +
> > >> +To use the :ref:`format` ioctls applications set the ``type`` of the
> > >> +:ref:`v4l2_format <v4l2-format>` structure to
> > >> ``V4L2_BUF_TYPE_META_CAPTURE`` +and use the :ref:`v4l2_meta_format
> > >> <v4l2-meta-format>` ``meta`` member of the +``fmt`` union as needed per
> > >> the desired operation. The :ref:`v4l2-meta-format` +structure contains
> > >> two fields, ``dataformat`` is set by applications to the V4L2
> > > 
> > > I might not specify the number of number of fields here. It has high
> > > chances of not getting updated when more fields are added. Up to you.
> > 
> > This has been copied from dev-sdr.rst. I can drop the last sentence
> > completely as the parameters are described in the table below. Hans, any
> > opinion ?
> 
> How about this ?
> 
> To use the :ref:`format` ioctls applications set the ``type`` of the

s/of/field of/

?

> :ref:`v4l2_format <v4l2-format>` structure to ``V4L2_BUF_TYPE_META_CAPTURE``
> and use the :ref:`v4l2_meta_format <v4l2-meta-format>` ``meta`` member of the
> ``fmt`` union as needed per the desired operation. Both drivers and 
> applications must set the remainder of the :ref:`v4l2_format <v4l2-format>` 
> structure to 0.

-- 
Sakari Ailus
e-mail: sakari.ailus@iki.fi	XMPP: sailus@retiisi.org.uk

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v2.2 1/4] v4l: Add metadata buffer type and format
  2016-08-17 12:20 [PATCH v2 0/4] R-Car VSP1 1-D Histogram support Laurent Pinchart
                   ` (3 preceding siblings ...)
  2016-08-17 12:20 ` [PATCH v2 4/4] v4l: vsp1: Don't create HGO entity when the userspace API is disabled Laurent Pinchart
@ 2016-09-05  8:08 ` Laurent Pinchart
  2016-09-05  8:10   ` Hans Verkuil
  2016-09-13 12:19 ` [PATCH v2 0/4] R-Car VSP1 1-D Histogram support Geert Uytterhoeven
  5 siblings, 1 reply; 17+ messages in thread
From: Laurent Pinchart @ 2016-09-05  8:08 UTC (permalink / raw)
  To: linux-media
  Cc: linux-renesas-soc, Sakari Ailus, Hans Verkuil, Guennadi Liakhovetski

The metadata buffer type is used to transfer metadata between userspace
and kernelspace through a V4L2 buffers queue. It comes with a new
metadata capture capability and format description.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Guennadi Liakhovetski <guennadi.liakhovetski@intel.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
Changes since v2.1:

- Updated include/uapi/linux/videodev2.h

Changes since v2:

- Dropped the reserved field from struct v4l2_meta_format
- Removed redundant documentation sentence
- Fixed typos

Changes since v1:

- Rebased on top of the DocBook to reST conversion

 Documentation/media/uapi/v4l/buffer.rst          |  8 +++
 Documentation/media/uapi/v4l/dev-meta.rst        | 63 ++++++++++++++++++++++++
 Documentation/media/uapi/v4l/devices.rst         |  1 +
 Documentation/media/uapi/v4l/vidioc-querycap.rst | 14 ++++--
 Documentation/media/videodev2.h.rst.exceptions   |  2 +
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c    | 19 +++++++
 drivers/media/v4l2-core/v4l2-dev.c               | 16 +++---
 drivers/media/v4l2-core/v4l2-ioctl.c             | 34 +++++++++++++
 drivers/media/v4l2-core/videobuf2-v4l2.c         |  3 ++
 include/media/v4l2-ioctl.h                       | 17 +++++++
 include/trace/events/v4l2.h                      |  1 +
 include/uapi/linux/videodev2.h                   | 13 +++++
 12 files changed, 182 insertions(+), 9 deletions(-)
 create mode 100644 Documentation/media/uapi/v4l/dev-meta.rst

diff --git a/Documentation/media/uapi/v4l/buffer.rst b/Documentation/media/uapi/v4l/buffer.rst
index 5deb4a46f992..b5177cc63b86 100644
--- a/Documentation/media/uapi/v4l/buffer.rst
+++ b/Documentation/media/uapi/v4l/buffer.rst
@@ -499,6 +499,14 @@ enum v4l2_buf_type
        -  Buffer for Software Defined Radio (SDR) output stream, see
 	  :ref:`sdr`.
 
+    -  .. row 13
+
+       -  ``V4L2_BUF_TYPE_META_CAPTURE``
+
+       -  13
+
+       -  Buffer for metadata capture, see :ref:`metadata`.
+
 
 
 .. _buffer-flags:
diff --git a/Documentation/media/uapi/v4l/dev-meta.rst b/Documentation/media/uapi/v4l/dev-meta.rst
new file mode 100644
index 000000000000..d3a33fea9cc9
--- /dev/null
+++ b/Documentation/media/uapi/v4l/dev-meta.rst
@@ -0,0 +1,63 @@
+.. -*- coding: utf-8; mode: rst -*-
+
+.. _metadata:
+
+******************
+Metadata Interface
+******************
+
+Metadata refers to any non-image data that supplements video frames with
+additional information. This may include statistics computed over the image
+or frame capture parameters supplied by the image source. This interface is
+intended for transfer of metadata to userspace and control of that operation.
+
+The metadata interface is implemented on video capture device nodes. The device
+can be dedicated to metadata or can implement both video and metadata capture
+as specified in its reported capabilities.
+
+.. note::
+
+    This is an :ref:`experimental` interface and may
+    change in the future.
+
+Querying Capabilities
+=====================
+
+Device nodes supporting the metadata interface set the ``V4L2_CAP_META_CAPTURE``
+flag in the ``device_caps`` field of the
+:ref:`v4l2_capability <v4l2-capability>` structure returned by the
+:ref:`VIDIOC_QUERYCAP` ioctl. That flag means the device can capture
+metadata to memory.
+
+At least one of the read/write or streaming I/O methods must be supported.
+
+
+Data Format Negotiation
+=======================
+
+The metadata device uses the :ref:`format` ioctls to select the capture format.
+The metadata buffer content format is bound to that selected format. In addition
+to the basic :ref:`format` ioctls, the :ref:`VIDIOC_ENUM_FMT` ioctl must be
+supported as well.
+
+To use the :ref:`format` ioctls applications set the ``type`` field of the
+:ref:`v4l2_format <v4l2-format>` structure to ``V4L2_BUF_TYPE_META_CAPTURE``
+and use the :ref:`v4l2_meta_format <v4l2-meta-format>` ``meta`` member of the
+``fmt`` union as needed per the desired operation. Both drivers and applications
+must set the remainder of the :ref:`v4l2_format <v4l2-format>` structure to 0.
+
+.. _v4l2-meta-format:
+.. flat-table:: struct v4l2_meta_format
+    :header-rows:  0
+    :stub-columns: 0
+    :widths:       1 1 2
+
+    * - __u32
+      - ``dataformat``
+      - The data format, set by the application. This is a little endian
+        :ref:`four character code <v4l2-fourcc>`. V4L2 defines metadata formats
+        in :ref:`meta-formats`.
+    * - __u32
+      - ``buffersize``
+      - Maximum buffer size in bytes required for data. The value is set by the
+        driver.
diff --git a/Documentation/media/uapi/v4l/devices.rst b/Documentation/media/uapi/v4l/devices.rst
index aed0ce11d1f8..961e7fb62063 100644
--- a/Documentation/media/uapi/v4l/devices.rst
+++ b/Documentation/media/uapi/v4l/devices.rst
@@ -24,3 +24,4 @@ Interfaces
     dev-sdr
     dev-event
     dev-subdev
+    dev-meta
diff --git a/Documentation/media/uapi/v4l/vidioc-querycap.rst b/Documentation/media/uapi/v4l/vidioc-querycap.rst
index b10fed313f99..734fae6fc5e4 100644
--- a/Documentation/media/uapi/v4l/vidioc-querycap.rst
+++ b/Documentation/media/uapi/v4l/vidioc-querycap.rst
@@ -387,6 +387,14 @@ specification the ioctl returns an ``EINVAL`` error code.
 
     -  .. row 23
 
+       -  ``V4L2_CAP_META_CAPTURE``
+
+       -  0x00800000
+
+       -  The device supports the :ref:`metadata` capture interface.
+
+    -  .. row 24
+
        -  ``V4L2_CAP_READWRITE``
 
        -  0x01000000
@@ -394,7 +402,7 @@ specification the ioctl returns an ``EINVAL`` error code.
        -  The device supports the :ref:`read() <rw>` and/or
 	  :ref:`write() <rw>` I/O methods.
 
-    -  .. row 24
+    -  .. row 25
 
        -  ``V4L2_CAP_ASYNCIO``
 
@@ -402,7 +410,7 @@ specification the ioctl returns an ``EINVAL`` error code.
 
        -  The device supports the :ref:`asynchronous <async>` I/O methods.
 
-    -  .. row 25
+    -  .. row 26
 
        -  ``V4L2_CAP_STREAMING``
 
@@ -410,7 +418,7 @@ specification the ioctl returns an ``EINVAL`` error code.
 
        -  The device supports the :ref:`streaming <mmap>` I/O method.
 
-    -  .. row 26
+    -  .. row 27
 
        -  ``V4L2_CAP_DEVICE_CAPS``
 
diff --git a/Documentation/media/videodev2.h.rst.exceptions b/Documentation/media/videodev2.h.rst.exceptions
index 9bb9a6cc39d8..d1275725d367 100644
--- a/Documentation/media/videodev2.h.rst.exceptions
+++ b/Documentation/media/videodev2.h.rst.exceptions
@@ -27,6 +27,7 @@ replace symbol V4L2_FIELD_SEQ_TB v4l2-field
 replace symbol V4L2_FIELD_TOP v4l2-field
 
 # Documented enum v4l2_buf_type
+replace symbol V4L2_BUF_TYPE_META_CAPTURE v4l2-buf-type
 replace symbol V4L2_BUF_TYPE_SDR_CAPTURE v4l2-buf-type
 replace symbol V4L2_BUF_TYPE_SDR_OUTPUT v4l2-buf-type
 replace symbol V4L2_BUF_TYPE_SLICED_VBI_CAPTURE v4l2-buf-type
@@ -148,6 +149,7 @@ replace define V4L2_CAP_MODULATOR device-capabilities
 replace define V4L2_CAP_SDR_CAPTURE device-capabilities
 replace define V4L2_CAP_EXT_PIX_FORMAT device-capabilities
 replace define V4L2_CAP_SDR_OUTPUT device-capabilities
+replace define V4L2_CAP_META_CAPTURE device-capabilities
 replace define V4L2_CAP_READWRITE device-capabilities
 replace define V4L2_CAP_ASYNCIO device-capabilities
 replace define V4L2_CAP_STREAMING device-capabilities
diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index bacecbd68a6d..da2d836e8887 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -161,6 +161,20 @@ static inline int put_v4l2_sdr_format(struct v4l2_sdr_format *kp, struct v4l2_sd
 	return 0;
 }
 
+static inline int get_v4l2_meta_format(struct v4l2_meta_format *kp, struct v4l2_meta_format __user *up)
+{
+	if (copy_from_user(kp, up, sizeof(struct v4l2_meta_format)))
+		return -EFAULT;
+	return 0;
+}
+
+static inline int put_v4l2_meta_format(struct v4l2_meta_format *kp, struct v4l2_meta_format __user *up)
+{
+	if (copy_to_user(up, kp, sizeof(struct v4l2_meta_format)))
+		return -EFAULT;
+	return 0;
+}
+
 struct v4l2_format32 {
 	__u32	type;	/* enum v4l2_buf_type */
 	union {
@@ -170,6 +184,7 @@ struct v4l2_format32 {
 		struct v4l2_vbi_format	vbi;
 		struct v4l2_sliced_vbi_format	sliced;
 		struct v4l2_sdr_format	sdr;
+		struct v4l2_meta_format	meta;
 		__u8	raw_data[200];        /* user-defined */
 	} fmt;
 };
@@ -216,6 +231,8 @@ static int __get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __us
 	case V4L2_BUF_TYPE_SDR_CAPTURE:
 	case V4L2_BUF_TYPE_SDR_OUTPUT:
 		return get_v4l2_sdr_format(&kp->fmt.sdr, &up->fmt.sdr);
+	case V4L2_BUF_TYPE_META_CAPTURE:
+		return get_v4l2_meta_format(&kp->fmt.meta, &up->fmt.meta);
 	default:
 		pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
 								kp->type);
@@ -263,6 +280,8 @@ static int __put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __us
 	case V4L2_BUF_TYPE_SDR_CAPTURE:
 	case V4L2_BUF_TYPE_SDR_OUTPUT:
 		return put_v4l2_sdr_format(&kp->fmt.sdr, &up->fmt.sdr);
+	case V4L2_BUF_TYPE_META_CAPTURE:
+		return put_v4l2_meta_format(&kp->fmt.meta, &up->fmt.meta);
 	default:
 		pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
 								kp->type);
diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
index e6da353b39bc..70af31210cd3 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -574,30 +574,34 @@ static void determine_valid_ioctls(struct video_device *vdev)
 		set_bit(_IOC_NR(VIDIOC_ENUM_FREQ_BANDS), valid_ioctls);
 
 	if (is_vid) {
-		/* video specific ioctls */
+		/* video and metadata specific ioctls */
 		if ((is_rx && (ops->vidioc_enum_fmt_vid_cap ||
 			       ops->vidioc_enum_fmt_vid_cap_mplane ||
-			       ops->vidioc_enum_fmt_vid_overlay)) ||
+			       ops->vidioc_enum_fmt_vid_overlay ||
+			       ops->vidioc_enum_fmt_meta_cap)) ||
 		    (is_tx && (ops->vidioc_enum_fmt_vid_out ||
 			       ops->vidioc_enum_fmt_vid_out_mplane)))
 			set_bit(_IOC_NR(VIDIOC_ENUM_FMT), valid_ioctls);
 		if ((is_rx && (ops->vidioc_g_fmt_vid_cap ||
 			       ops->vidioc_g_fmt_vid_cap_mplane ||
-			       ops->vidioc_g_fmt_vid_overlay)) ||
+			       ops->vidioc_g_fmt_vid_overlay ||
+			       ops->vidioc_g_fmt_meta_cap)) ||
 		    (is_tx && (ops->vidioc_g_fmt_vid_out ||
 			       ops->vidioc_g_fmt_vid_out_mplane ||
 			       ops->vidioc_g_fmt_vid_out_overlay)))
 			 set_bit(_IOC_NR(VIDIOC_G_FMT), valid_ioctls);
 		if ((is_rx && (ops->vidioc_s_fmt_vid_cap ||
 			       ops->vidioc_s_fmt_vid_cap_mplane ||
-			       ops->vidioc_s_fmt_vid_overlay)) ||
+			       ops->vidioc_s_fmt_vid_overlay ||
+			       ops->vidioc_s_fmt_meta_cap)) ||
 		    (is_tx && (ops->vidioc_s_fmt_vid_out ||
 			       ops->vidioc_s_fmt_vid_out_mplane ||
 			       ops->vidioc_s_fmt_vid_out_overlay)))
 			 set_bit(_IOC_NR(VIDIOC_S_FMT), valid_ioctls);
 		if ((is_rx && (ops->vidioc_try_fmt_vid_cap ||
 			       ops->vidioc_try_fmt_vid_cap_mplane ||
-			       ops->vidioc_try_fmt_vid_overlay)) ||
+			       ops->vidioc_try_fmt_vid_overlay ||
+			       ops->vidioc_try_fmt_meta_cap)) ||
 		    (is_tx && (ops->vidioc_try_fmt_vid_out ||
 			       ops->vidioc_try_fmt_vid_out_mplane ||
 			       ops->vidioc_try_fmt_vid_out_overlay)))
@@ -663,7 +667,7 @@ static void determine_valid_ioctls(struct video_device *vdev)
 	}
 
 	if (is_vid || is_vbi || is_sdr) {
-		/* ioctls valid for video, vbi or sdr */
+		/* ioctls valid for video, metadata, vbi or sdr */
 		SET_VALID_IOCTL(ops, VIDIOC_REQBUFS, vidioc_reqbufs);
 		SET_VALID_IOCTL(ops, VIDIOC_QUERYBUF, vidioc_querybuf);
 		SET_VALID_IOCTL(ops, VIDIOC_QBUF, vidioc_qbuf);
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index 51a0fa144392..1fce6b084b53 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -155,6 +155,7 @@ const char *v4l2_type_names[] = {
 	[V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE] = "vid-out-mplane",
 	[V4L2_BUF_TYPE_SDR_CAPTURE]        = "sdr-cap",
 	[V4L2_BUF_TYPE_SDR_OUTPUT]         = "sdr-out",
+	[V4L2_BUF_TYPE_META_CAPTURE]       = "meta-cap",
 };
 EXPORT_SYMBOL(v4l2_type_names);
 
@@ -249,6 +250,7 @@ static void v4l_print_format(const void *arg, bool write_only)
 	const struct v4l2_sliced_vbi_format *sliced;
 	const struct v4l2_window *win;
 	const struct v4l2_sdr_format *sdr;
+	const struct v4l2_meta_format *meta;
 	unsigned i;
 
 	pr_cont("type=%s", prt_names(p->type, v4l2_type_names));
@@ -336,6 +338,15 @@ static void v4l_print_format(const void *arg, bool write_only)
 			(sdr->pixelformat >> 16) & 0xff,
 			(sdr->pixelformat >> 24) & 0xff);
 		break;
+	case V4L2_BUF_TYPE_META_CAPTURE:
+		meta = &p->fmt.meta;
+		pr_cont(", dataformat=%c%c%c%c, buffersize=%u\n",
+			(meta->dataformat >>  0) & 0xff,
+			(meta->dataformat >>  8) & 0xff,
+			(meta->dataformat >> 16) & 0xff,
+			(meta->dataformat >> 24) & 0xff,
+			meta->buffersize);
+		break;
 	}
 }
 
@@ -981,6 +992,10 @@ static int check_fmt(struct file *file, enum v4l2_buf_type type)
 		if (is_sdr && is_tx && ops->vidioc_g_fmt_sdr_out)
 			return 0;
 		break;
+	case V4L2_BUF_TYPE_META_CAPTURE:
+		if (is_vid && is_rx && ops->vidioc_g_fmt_meta_cap)
+			return 0;
+		break;
 	default:
 		break;
 	}
@@ -1349,6 +1364,11 @@ static int v4l_enum_fmt(const struct v4l2_ioctl_ops *ops,
 			break;
 		ret = ops->vidioc_enum_fmt_sdr_out(file, fh, arg);
 		break;
+	case V4L2_BUF_TYPE_META_CAPTURE:
+		if (unlikely(!is_rx || !is_vid || !ops->vidioc_enum_fmt_meta_cap))
+			break;
+		ret = ops->vidioc_enum_fmt_meta_cap(file, fh, arg);
+		break;
 	}
 	if (ret == 0)
 		v4l_fill_fmtdesc(p);
@@ -1447,6 +1467,10 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops,
 		if (unlikely(!is_tx || !is_sdr || !ops->vidioc_g_fmt_sdr_out))
 			break;
 		return ops->vidioc_g_fmt_sdr_out(file, fh, arg);
+	case V4L2_BUF_TYPE_META_CAPTURE:
+		if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_meta_cap))
+			break;
+		return ops->vidioc_g_fmt_meta_cap(file, fh, arg);
 	}
 	return -EINVAL;
 }
@@ -1534,6 +1558,11 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,
 			break;
 		CLEAR_AFTER_FIELD(p, fmt.sdr);
 		return ops->vidioc_s_fmt_sdr_out(file, fh, arg);
+	case V4L2_BUF_TYPE_META_CAPTURE:
+		if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_meta_cap))
+			break;
+		CLEAR_AFTER_FIELD(p, fmt.meta);
+		return ops->vidioc_s_fmt_meta_cap(file, fh, arg);
 	}
 	return -EINVAL;
 }
@@ -1618,6 +1647,11 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops,
 			break;
 		CLEAR_AFTER_FIELD(p, fmt.sdr);
 		return ops->vidioc_try_fmt_sdr_out(file, fh, arg);
+	case V4L2_BUF_TYPE_META_CAPTURE:
+		if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_meta_cap))
+			break;
+		CLEAR_AFTER_FIELD(p, fmt.meta);
+		return ops->vidioc_try_fmt_meta_cap(file, fh, arg);
 	}
 	return -EINVAL;
 }
diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c
index 9cfbb6e4bc28..7216668d1056 100644
--- a/drivers/media/v4l2-core/videobuf2-v4l2.c
+++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
@@ -575,6 +575,9 @@ int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
 	case V4L2_BUF_TYPE_SDR_OUTPUT:
 		requested_sizes[0] = f->fmt.sdr.buffersize;
 		break;
+	case V4L2_BUF_TYPE_META_CAPTURE:
+		requested_sizes[0] = f->fmt.meta.buffersize;
+		break;
 	default:
 		return -EINVAL;
 	}
diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
index 8b1d19bc9b0e..a32dcf78d4a3 100644
--- a/include/media/v4l2-ioctl.h
+++ b/include/media/v4l2-ioctl.h
@@ -43,6 +43,9 @@ struct v4l2_fh;
  * @vidioc_enum_fmt_sdr_out: pointer to the function that implements
  *	:ref:`VIDIOC_ENUM_FMT <vidioc_enum_fmt>` ioctl logic
  *	for Software Defined Radio output
+ * @vidioc_enum_fmt_meta_cap: pointer to the function that implements
+ *	:ref:`VIDIOC_ENUM_FMT <vidioc_enum_fmt>` ioctl logic
+ *	for metadata capture
  * @vidioc_g_fmt_vid_cap: pointer to the function that implements
  *	:ref:`VIDIOC_G_FMT <vidioc_g_fmt>` ioctl logic for video capture
  *	in single plane mode
@@ -73,6 +76,8 @@ struct v4l2_fh;
  * @vidioc_g_fmt_sdr_out: pointer to the function that implements
  *	:ref:`VIDIOC_G_FMT <vidioc_g_fmt>` ioctl logic for Software Defined
  *	Radio output
+ * @vidioc_g_fmt_meta_cap: pointer to the function that implements
+ *	:ref:`VIDIOC_G_FMT <vidioc_g_fmt>` ioctl logic for metadata capture
  * @vidioc_s_fmt_vid_cap: pointer to the function that implements
  *	:ref:`VIDIOC_S_FMT <vidioc_g_fmt>` ioctl logic for video capture
  *	in single plane mode
@@ -103,6 +108,8 @@ struct v4l2_fh;
  * @vidioc_s_fmt_sdr_out: pointer to the function that implements
  *	:ref:`VIDIOC_S_FMT <vidioc_g_fmt>` ioctl logic for Software Defined
  *	Radio output
+ * @vidioc_s_fmt_meta_cap: pointer to the function that implements
+ *	:ref:`VIDIOC_S_FMT <vidioc_g_fmt>` ioctl logic for metadata capture
  * @vidioc_try_fmt_vid_cap: pointer to the function that implements
  *	:ref:`VIDIOC_TRY_FMT <vidioc_g_fmt>` ioctl logic for video capture
  *	in single plane mode
@@ -135,6 +142,8 @@ struct v4l2_fh;
  * @vidioc_try_fmt_sdr_out: pointer to the function that implements
  *	:ref:`VIDIOC_TRY_FMT <vidioc_g_fmt>` ioctl logic for Software Defined
  *	Radio output
+ * @vidioc_try_fmt_meta_cap: pointer to the function that implements
+ *	:ref:`VIDIOC_TRY_FMT <vidioc_g_fmt>` ioctl logic for metadata capture
  * @vidioc_reqbufs: pointer to the function that implements
  *	:ref:`VIDIOC_REQBUFS <vidioc_reqbufs>` ioctl
  * @vidioc_querybuf: pointer to the function that implements
@@ -304,6 +313,8 @@ struct v4l2_ioctl_ops {
 					    struct v4l2_fmtdesc *f);
 	int (*vidioc_enum_fmt_sdr_out)     (struct file *file, void *fh,
 					    struct v4l2_fmtdesc *f);
+	int (*vidioc_enum_fmt_meta_cap)    (struct file *file, void *fh,
+					    struct v4l2_fmtdesc *f);
 
 	/* VIDIOC_G_FMT handlers */
 	int (*vidioc_g_fmt_vid_cap)    (struct file *file, void *fh,
@@ -330,6 +341,8 @@ struct v4l2_ioctl_ops {
 					struct v4l2_format *f);
 	int (*vidioc_g_fmt_sdr_out)    (struct file *file, void *fh,
 					struct v4l2_format *f);
+	int (*vidioc_g_fmt_meta_cap)   (struct file *file, void *fh,
+					struct v4l2_format *f);
 
 	/* VIDIOC_S_FMT handlers */
 	int (*vidioc_s_fmt_vid_cap)    (struct file *file, void *fh,
@@ -356,6 +369,8 @@ struct v4l2_ioctl_ops {
 					struct v4l2_format *f);
 	int (*vidioc_s_fmt_sdr_out)    (struct file *file, void *fh,
 					struct v4l2_format *f);
+	int (*vidioc_s_fmt_meta_cap)   (struct file *file, void *fh,
+					struct v4l2_format *f);
 
 	/* VIDIOC_TRY_FMT handlers */
 	int (*vidioc_try_fmt_vid_cap)    (struct file *file, void *fh,
@@ -382,6 +397,8 @@ struct v4l2_ioctl_ops {
 					  struct v4l2_format *f);
 	int (*vidioc_try_fmt_sdr_out)    (struct file *file, void *fh,
 					  struct v4l2_format *f);
+	int (*vidioc_try_fmt_meta_cap)   (struct file *file, void *fh,
+					  struct v4l2_format *f);
 
 	/* Buffer handlers */
 	int (*vidioc_reqbufs) (struct file *file, void *fh, struct v4l2_requestbuffers *b);
diff --git a/include/trace/events/v4l2.h b/include/trace/events/v4l2.h
index ee7754c6e4a1..b3a85b3df53e 100644
--- a/include/trace/events/v4l2.h
+++ b/include/trace/events/v4l2.h
@@ -29,6 +29,7 @@
 	EM( V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,  "VIDEO_OUTPUT_MPLANE" )	\
 	EM( V4L2_BUF_TYPE_SDR_CAPTURE,          "SDR_CAPTURE" )		\
 	EM( V4L2_BUF_TYPE_SDR_OUTPUT,           "SDR_OUTPUT" )		\
+	EM( V4L2_BUF_TYPE_META_CAPTURE,		"META_CAPTURE" )	\
 	EMe(V4L2_BUF_TYPE_PRIVATE,		"PRIVATE" )
 
 SHOW_TYPE
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 724f43e69d03..e0afe68f24ee 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -143,6 +143,7 @@ enum v4l2_buf_type {
 	V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE  = 10,
 	V4L2_BUF_TYPE_SDR_CAPTURE          = 11,
 	V4L2_BUF_TYPE_SDR_OUTPUT           = 12,
+	V4L2_BUF_TYPE_META_CAPTURE         = 13,
 	/* Deprecated, do not use */
 	V4L2_BUF_TYPE_PRIVATE              = 0x80,
 };
@@ -435,6 +436,7 @@ struct v4l2_capability {
 #define V4L2_CAP_SDR_CAPTURE		0x00100000  /* Is a SDR capture device */
 #define V4L2_CAP_EXT_PIX_FORMAT		0x00200000  /* Supports the extended pixel format */
 #define V4L2_CAP_SDR_OUTPUT		0x00400000  /* Is a SDR output device */
+#define V4L2_CAP_META_CAPTURE		0x00800000  /* Is a metadata capture device */
 
 #define V4L2_CAP_READWRITE              0x01000000  /* read/write systemcalls */
 #define V4L2_CAP_ASYNCIO                0x02000000  /* async I/O */
@@ -2002,6 +2004,16 @@ struct v4l2_sdr_format {
 } __attribute__ ((packed));
 
 /**
+ * struct v4l2_meta_format - metadata format definition
+ * @dataformat:		little endian four character code (fourcc)
+ * @buffersize:		maximum size in bytes required for data
+ */
+struct v4l2_meta_format {
+	__u32				dataformat;
+	__u32				buffersize;
+} __attribute__ ((packed));
+
+/**
  * struct v4l2_format - stream data format
  * @type:	enum v4l2_buf_type; type of the data stream
  * @pix:	definition of an image format
@@ -2020,6 +2032,7 @@ struct v4l2_format {
 		struct v4l2_vbi_format		vbi;     /* V4L2_BUF_TYPE_VBI_CAPTURE */
 		struct v4l2_sliced_vbi_format	sliced;  /* V4L2_BUF_TYPE_SLICED_VBI_CAPTURE */
 		struct v4l2_sdr_format		sdr;     /* V4L2_BUF_TYPE_SDR_CAPTURE */
+		struct v4l2_meta_format		meta;    /* V4L2_BUF_TYPE_META_CAPTURE */
 		__u8	raw_data[200];                   /* user-defined */
 	} fmt;
 };
-- 
Regards,

Laurent Pinchart


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH v2.2 1/4] v4l: Add metadata buffer type and format
  2016-09-05  8:08 ` [PATCH v2.2 1/4] v4l: Add metadata buffer type and format Laurent Pinchart
@ 2016-09-05  8:10   ` Hans Verkuil
  0 siblings, 0 replies; 17+ messages in thread
From: Hans Verkuil @ 2016-09-05  8:10 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media
  Cc: linux-renesas-soc, Sakari Ailus, Hans Verkuil, Guennadi Liakhovetski

On 09/05/2016 10:08 AM, Laurent Pinchart wrote:
> The metadata buffer type is used to transfer metadata between userspace
> and kernelspace through a V4L2 buffers queue. It comes with a new
> metadata capture capability and format description.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> Tested-by: Guennadi Liakhovetski <guennadi.liakhovetski@intel.com>
> Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>

Acked-by: Hans Verkuil <hans.verkuil@cisco.com>

Thanks!

	Hans

> ---
> Changes since v2.1:
> 
> - Updated include/uapi/linux/videodev2.h
> 
> Changes since v2:
> 
> - Dropped the reserved field from struct v4l2_meta_format
> - Removed redundant documentation sentence
> - Fixed typos
> 
> Changes since v1:
> 
> - Rebased on top of the DocBook to reST conversion
> 
>  Documentation/media/uapi/v4l/buffer.rst          |  8 +++
>  Documentation/media/uapi/v4l/dev-meta.rst        | 63 ++++++++++++++++++++++++
>  Documentation/media/uapi/v4l/devices.rst         |  1 +
>  Documentation/media/uapi/v4l/vidioc-querycap.rst | 14 ++++--
>  Documentation/media/videodev2.h.rst.exceptions   |  2 +
>  drivers/media/v4l2-core/v4l2-compat-ioctl32.c    | 19 +++++++
>  drivers/media/v4l2-core/v4l2-dev.c               | 16 +++---
>  drivers/media/v4l2-core/v4l2-ioctl.c             | 34 +++++++++++++
>  drivers/media/v4l2-core/videobuf2-v4l2.c         |  3 ++
>  include/media/v4l2-ioctl.h                       | 17 +++++++
>  include/trace/events/v4l2.h                      |  1 +
>  include/uapi/linux/videodev2.h                   | 13 +++++
>  12 files changed, 182 insertions(+), 9 deletions(-)
>  create mode 100644 Documentation/media/uapi/v4l/dev-meta.rst
> 
> diff --git a/Documentation/media/uapi/v4l/buffer.rst b/Documentation/media/uapi/v4l/buffer.rst
> index 5deb4a46f992..b5177cc63b86 100644
> --- a/Documentation/media/uapi/v4l/buffer.rst
> +++ b/Documentation/media/uapi/v4l/buffer.rst
> @@ -499,6 +499,14 @@ enum v4l2_buf_type
>         -  Buffer for Software Defined Radio (SDR) output stream, see
>  	  :ref:`sdr`.
>  
> +    -  .. row 13
> +
> +       -  ``V4L2_BUF_TYPE_META_CAPTURE``
> +
> +       -  13
> +
> +       -  Buffer for metadata capture, see :ref:`metadata`.
> +
>  
>  
>  .. _buffer-flags:
> diff --git a/Documentation/media/uapi/v4l/dev-meta.rst b/Documentation/media/uapi/v4l/dev-meta.rst
> new file mode 100644
> index 000000000000..d3a33fea9cc9
> --- /dev/null
> +++ b/Documentation/media/uapi/v4l/dev-meta.rst
> @@ -0,0 +1,63 @@
> +.. -*- coding: utf-8; mode: rst -*-
> +
> +.. _metadata:
> +
> +******************
> +Metadata Interface
> +******************
> +
> +Metadata refers to any non-image data that supplements video frames with
> +additional information. This may include statistics computed over the image
> +or frame capture parameters supplied by the image source. This interface is
> +intended for transfer of metadata to userspace and control of that operation.
> +
> +The metadata interface is implemented on video capture device nodes. The device
> +can be dedicated to metadata or can implement both video and metadata capture
> +as specified in its reported capabilities.
> +
> +.. note::
> +
> +    This is an :ref:`experimental` interface and may
> +    change in the future.
> +
> +Querying Capabilities
> +=====================
> +
> +Device nodes supporting the metadata interface set the ``V4L2_CAP_META_CAPTURE``
> +flag in the ``device_caps`` field of the
> +:ref:`v4l2_capability <v4l2-capability>` structure returned by the
> +:ref:`VIDIOC_QUERYCAP` ioctl. That flag means the device can capture
> +metadata to memory.
> +
> +At least one of the read/write or streaming I/O methods must be supported.
> +
> +
> +Data Format Negotiation
> +=======================
> +
> +The metadata device uses the :ref:`format` ioctls to select the capture format.
> +The metadata buffer content format is bound to that selected format. In addition
> +to the basic :ref:`format` ioctls, the :ref:`VIDIOC_ENUM_FMT` ioctl must be
> +supported as well.
> +
> +To use the :ref:`format` ioctls applications set the ``type`` field of the
> +:ref:`v4l2_format <v4l2-format>` structure to ``V4L2_BUF_TYPE_META_CAPTURE``
> +and use the :ref:`v4l2_meta_format <v4l2-meta-format>` ``meta`` member of the
> +``fmt`` union as needed per the desired operation. Both drivers and applications
> +must set the remainder of the :ref:`v4l2_format <v4l2-format>` structure to 0.
> +
> +.. _v4l2-meta-format:
> +.. flat-table:: struct v4l2_meta_format
> +    :header-rows:  0
> +    :stub-columns: 0
> +    :widths:       1 1 2
> +
> +    * - __u32
> +      - ``dataformat``
> +      - The data format, set by the application. This is a little endian
> +        :ref:`four character code <v4l2-fourcc>`. V4L2 defines metadata formats
> +        in :ref:`meta-formats`.
> +    * - __u32
> +      - ``buffersize``
> +      - Maximum buffer size in bytes required for data. The value is set by the
> +        driver.
> diff --git a/Documentation/media/uapi/v4l/devices.rst b/Documentation/media/uapi/v4l/devices.rst
> index aed0ce11d1f8..961e7fb62063 100644
> --- a/Documentation/media/uapi/v4l/devices.rst
> +++ b/Documentation/media/uapi/v4l/devices.rst
> @@ -24,3 +24,4 @@ Interfaces
>      dev-sdr
>      dev-event
>      dev-subdev
> +    dev-meta
> diff --git a/Documentation/media/uapi/v4l/vidioc-querycap.rst b/Documentation/media/uapi/v4l/vidioc-querycap.rst
> index b10fed313f99..734fae6fc5e4 100644
> --- a/Documentation/media/uapi/v4l/vidioc-querycap.rst
> +++ b/Documentation/media/uapi/v4l/vidioc-querycap.rst
> @@ -387,6 +387,14 @@ specification the ioctl returns an ``EINVAL`` error code.
>  
>      -  .. row 23
>  
> +       -  ``V4L2_CAP_META_CAPTURE``
> +
> +       -  0x00800000
> +
> +       -  The device supports the :ref:`metadata` capture interface.
> +
> +    -  .. row 24
> +
>         -  ``V4L2_CAP_READWRITE``
>  
>         -  0x01000000
> @@ -394,7 +402,7 @@ specification the ioctl returns an ``EINVAL`` error code.
>         -  The device supports the :ref:`read() <rw>` and/or
>  	  :ref:`write() <rw>` I/O methods.
>  
> -    -  .. row 24
> +    -  .. row 25
>  
>         -  ``V4L2_CAP_ASYNCIO``
>  
> @@ -402,7 +410,7 @@ specification the ioctl returns an ``EINVAL`` error code.
>  
>         -  The device supports the :ref:`asynchronous <async>` I/O methods.
>  
> -    -  .. row 25
> +    -  .. row 26
>  
>         -  ``V4L2_CAP_STREAMING``
>  
> @@ -410,7 +418,7 @@ specification the ioctl returns an ``EINVAL`` error code.
>  
>         -  The device supports the :ref:`streaming <mmap>` I/O method.
>  
> -    -  .. row 26
> +    -  .. row 27
>  
>         -  ``V4L2_CAP_DEVICE_CAPS``
>  
> diff --git a/Documentation/media/videodev2.h.rst.exceptions b/Documentation/media/videodev2.h.rst.exceptions
> index 9bb9a6cc39d8..d1275725d367 100644
> --- a/Documentation/media/videodev2.h.rst.exceptions
> +++ b/Documentation/media/videodev2.h.rst.exceptions
> @@ -27,6 +27,7 @@ replace symbol V4L2_FIELD_SEQ_TB v4l2-field
>  replace symbol V4L2_FIELD_TOP v4l2-field
>  
>  # Documented enum v4l2_buf_type
> +replace symbol V4L2_BUF_TYPE_META_CAPTURE v4l2-buf-type
>  replace symbol V4L2_BUF_TYPE_SDR_CAPTURE v4l2-buf-type
>  replace symbol V4L2_BUF_TYPE_SDR_OUTPUT v4l2-buf-type
>  replace symbol V4L2_BUF_TYPE_SLICED_VBI_CAPTURE v4l2-buf-type
> @@ -148,6 +149,7 @@ replace define V4L2_CAP_MODULATOR device-capabilities
>  replace define V4L2_CAP_SDR_CAPTURE device-capabilities
>  replace define V4L2_CAP_EXT_PIX_FORMAT device-capabilities
>  replace define V4L2_CAP_SDR_OUTPUT device-capabilities
> +replace define V4L2_CAP_META_CAPTURE device-capabilities
>  replace define V4L2_CAP_READWRITE device-capabilities
>  replace define V4L2_CAP_ASYNCIO device-capabilities
>  replace define V4L2_CAP_STREAMING device-capabilities
> diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
> index bacecbd68a6d..da2d836e8887 100644
> --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
> +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
> @@ -161,6 +161,20 @@ static inline int put_v4l2_sdr_format(struct v4l2_sdr_format *kp, struct v4l2_sd
>  	return 0;
>  }
>  
> +static inline int get_v4l2_meta_format(struct v4l2_meta_format *kp, struct v4l2_meta_format __user *up)
> +{
> +	if (copy_from_user(kp, up, sizeof(struct v4l2_meta_format)))
> +		return -EFAULT;
> +	return 0;
> +}
> +
> +static inline int put_v4l2_meta_format(struct v4l2_meta_format *kp, struct v4l2_meta_format __user *up)
> +{
> +	if (copy_to_user(up, kp, sizeof(struct v4l2_meta_format)))
> +		return -EFAULT;
> +	return 0;
> +}
> +
>  struct v4l2_format32 {
>  	__u32	type;	/* enum v4l2_buf_type */
>  	union {
> @@ -170,6 +184,7 @@ struct v4l2_format32 {
>  		struct v4l2_vbi_format	vbi;
>  		struct v4l2_sliced_vbi_format	sliced;
>  		struct v4l2_sdr_format	sdr;
> +		struct v4l2_meta_format	meta;
>  		__u8	raw_data[200];        /* user-defined */
>  	} fmt;
>  };
> @@ -216,6 +231,8 @@ static int __get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __us
>  	case V4L2_BUF_TYPE_SDR_CAPTURE:
>  	case V4L2_BUF_TYPE_SDR_OUTPUT:
>  		return get_v4l2_sdr_format(&kp->fmt.sdr, &up->fmt.sdr);
> +	case V4L2_BUF_TYPE_META_CAPTURE:
> +		return get_v4l2_meta_format(&kp->fmt.meta, &up->fmt.meta);
>  	default:
>  		pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
>  								kp->type);
> @@ -263,6 +280,8 @@ static int __put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __us
>  	case V4L2_BUF_TYPE_SDR_CAPTURE:
>  	case V4L2_BUF_TYPE_SDR_OUTPUT:
>  		return put_v4l2_sdr_format(&kp->fmt.sdr, &up->fmt.sdr);
> +	case V4L2_BUF_TYPE_META_CAPTURE:
> +		return put_v4l2_meta_format(&kp->fmt.meta, &up->fmt.meta);
>  	default:
>  		pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
>  								kp->type);
> diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
> index e6da353b39bc..70af31210cd3 100644
> --- a/drivers/media/v4l2-core/v4l2-dev.c
> +++ b/drivers/media/v4l2-core/v4l2-dev.c
> @@ -574,30 +574,34 @@ static void determine_valid_ioctls(struct video_device *vdev)
>  		set_bit(_IOC_NR(VIDIOC_ENUM_FREQ_BANDS), valid_ioctls);
>  
>  	if (is_vid) {
> -		/* video specific ioctls */
> +		/* video and metadata specific ioctls */
>  		if ((is_rx && (ops->vidioc_enum_fmt_vid_cap ||
>  			       ops->vidioc_enum_fmt_vid_cap_mplane ||
> -			       ops->vidioc_enum_fmt_vid_overlay)) ||
> +			       ops->vidioc_enum_fmt_vid_overlay ||
> +			       ops->vidioc_enum_fmt_meta_cap)) ||
>  		    (is_tx && (ops->vidioc_enum_fmt_vid_out ||
>  			       ops->vidioc_enum_fmt_vid_out_mplane)))
>  			set_bit(_IOC_NR(VIDIOC_ENUM_FMT), valid_ioctls);
>  		if ((is_rx && (ops->vidioc_g_fmt_vid_cap ||
>  			       ops->vidioc_g_fmt_vid_cap_mplane ||
> -			       ops->vidioc_g_fmt_vid_overlay)) ||
> +			       ops->vidioc_g_fmt_vid_overlay ||
> +			       ops->vidioc_g_fmt_meta_cap)) ||
>  		    (is_tx && (ops->vidioc_g_fmt_vid_out ||
>  			       ops->vidioc_g_fmt_vid_out_mplane ||
>  			       ops->vidioc_g_fmt_vid_out_overlay)))
>  			 set_bit(_IOC_NR(VIDIOC_G_FMT), valid_ioctls);
>  		if ((is_rx && (ops->vidioc_s_fmt_vid_cap ||
>  			       ops->vidioc_s_fmt_vid_cap_mplane ||
> -			       ops->vidioc_s_fmt_vid_overlay)) ||
> +			       ops->vidioc_s_fmt_vid_overlay ||
> +			       ops->vidioc_s_fmt_meta_cap)) ||
>  		    (is_tx && (ops->vidioc_s_fmt_vid_out ||
>  			       ops->vidioc_s_fmt_vid_out_mplane ||
>  			       ops->vidioc_s_fmt_vid_out_overlay)))
>  			 set_bit(_IOC_NR(VIDIOC_S_FMT), valid_ioctls);
>  		if ((is_rx && (ops->vidioc_try_fmt_vid_cap ||
>  			       ops->vidioc_try_fmt_vid_cap_mplane ||
> -			       ops->vidioc_try_fmt_vid_overlay)) ||
> +			       ops->vidioc_try_fmt_vid_overlay ||
> +			       ops->vidioc_try_fmt_meta_cap)) ||
>  		    (is_tx && (ops->vidioc_try_fmt_vid_out ||
>  			       ops->vidioc_try_fmt_vid_out_mplane ||
>  			       ops->vidioc_try_fmt_vid_out_overlay)))
> @@ -663,7 +667,7 @@ static void determine_valid_ioctls(struct video_device *vdev)
>  	}
>  
>  	if (is_vid || is_vbi || is_sdr) {
> -		/* ioctls valid for video, vbi or sdr */
> +		/* ioctls valid for video, metadata, vbi or sdr */
>  		SET_VALID_IOCTL(ops, VIDIOC_REQBUFS, vidioc_reqbufs);
>  		SET_VALID_IOCTL(ops, VIDIOC_QUERYBUF, vidioc_querybuf);
>  		SET_VALID_IOCTL(ops, VIDIOC_QBUF, vidioc_qbuf);
> diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
> index 51a0fa144392..1fce6b084b53 100644
> --- a/drivers/media/v4l2-core/v4l2-ioctl.c
> +++ b/drivers/media/v4l2-core/v4l2-ioctl.c
> @@ -155,6 +155,7 @@ const char *v4l2_type_names[] = {
>  	[V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE] = "vid-out-mplane",
>  	[V4L2_BUF_TYPE_SDR_CAPTURE]        = "sdr-cap",
>  	[V4L2_BUF_TYPE_SDR_OUTPUT]         = "sdr-out",
> +	[V4L2_BUF_TYPE_META_CAPTURE]       = "meta-cap",
>  };
>  EXPORT_SYMBOL(v4l2_type_names);
>  
> @@ -249,6 +250,7 @@ static void v4l_print_format(const void *arg, bool write_only)
>  	const struct v4l2_sliced_vbi_format *sliced;
>  	const struct v4l2_window *win;
>  	const struct v4l2_sdr_format *sdr;
> +	const struct v4l2_meta_format *meta;
>  	unsigned i;
>  
>  	pr_cont("type=%s", prt_names(p->type, v4l2_type_names));
> @@ -336,6 +338,15 @@ static void v4l_print_format(const void *arg, bool write_only)
>  			(sdr->pixelformat >> 16) & 0xff,
>  			(sdr->pixelformat >> 24) & 0xff);
>  		break;
> +	case V4L2_BUF_TYPE_META_CAPTURE:
> +		meta = &p->fmt.meta;
> +		pr_cont(", dataformat=%c%c%c%c, buffersize=%u\n",
> +			(meta->dataformat >>  0) & 0xff,
> +			(meta->dataformat >>  8) & 0xff,
> +			(meta->dataformat >> 16) & 0xff,
> +			(meta->dataformat >> 24) & 0xff,
> +			meta->buffersize);
> +		break;
>  	}
>  }
>  
> @@ -981,6 +992,10 @@ static int check_fmt(struct file *file, enum v4l2_buf_type type)
>  		if (is_sdr && is_tx && ops->vidioc_g_fmt_sdr_out)
>  			return 0;
>  		break;
> +	case V4L2_BUF_TYPE_META_CAPTURE:
> +		if (is_vid && is_rx && ops->vidioc_g_fmt_meta_cap)
> +			return 0;
> +		break;
>  	default:
>  		break;
>  	}
> @@ -1349,6 +1364,11 @@ static int v4l_enum_fmt(const struct v4l2_ioctl_ops *ops,
>  			break;
>  		ret = ops->vidioc_enum_fmt_sdr_out(file, fh, arg);
>  		break;
> +	case V4L2_BUF_TYPE_META_CAPTURE:
> +		if (unlikely(!is_rx || !is_vid || !ops->vidioc_enum_fmt_meta_cap))
> +			break;
> +		ret = ops->vidioc_enum_fmt_meta_cap(file, fh, arg);
> +		break;
>  	}
>  	if (ret == 0)
>  		v4l_fill_fmtdesc(p);
> @@ -1447,6 +1467,10 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops,
>  		if (unlikely(!is_tx || !is_sdr || !ops->vidioc_g_fmt_sdr_out))
>  			break;
>  		return ops->vidioc_g_fmt_sdr_out(file, fh, arg);
> +	case V4L2_BUF_TYPE_META_CAPTURE:
> +		if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_meta_cap))
> +			break;
> +		return ops->vidioc_g_fmt_meta_cap(file, fh, arg);
>  	}
>  	return -EINVAL;
>  }
> @@ -1534,6 +1558,11 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,
>  			break;
>  		CLEAR_AFTER_FIELD(p, fmt.sdr);
>  		return ops->vidioc_s_fmt_sdr_out(file, fh, arg);
> +	case V4L2_BUF_TYPE_META_CAPTURE:
> +		if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_meta_cap))
> +			break;
> +		CLEAR_AFTER_FIELD(p, fmt.meta);
> +		return ops->vidioc_s_fmt_meta_cap(file, fh, arg);
>  	}
>  	return -EINVAL;
>  }
> @@ -1618,6 +1647,11 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops,
>  			break;
>  		CLEAR_AFTER_FIELD(p, fmt.sdr);
>  		return ops->vidioc_try_fmt_sdr_out(file, fh, arg);
> +	case V4L2_BUF_TYPE_META_CAPTURE:
> +		if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_meta_cap))
> +			break;
> +		CLEAR_AFTER_FIELD(p, fmt.meta);
> +		return ops->vidioc_try_fmt_meta_cap(file, fh, arg);
>  	}
>  	return -EINVAL;
>  }
> diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c
> index 9cfbb6e4bc28..7216668d1056 100644
> --- a/drivers/media/v4l2-core/videobuf2-v4l2.c
> +++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
> @@ -575,6 +575,9 @@ int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
>  	case V4L2_BUF_TYPE_SDR_OUTPUT:
>  		requested_sizes[0] = f->fmt.sdr.buffersize;
>  		break;
> +	case V4L2_BUF_TYPE_META_CAPTURE:
> +		requested_sizes[0] = f->fmt.meta.buffersize;
> +		break;
>  	default:
>  		return -EINVAL;
>  	}
> diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
> index 8b1d19bc9b0e..a32dcf78d4a3 100644
> --- a/include/media/v4l2-ioctl.h
> +++ b/include/media/v4l2-ioctl.h
> @@ -43,6 +43,9 @@ struct v4l2_fh;
>   * @vidioc_enum_fmt_sdr_out: pointer to the function that implements
>   *	:ref:`VIDIOC_ENUM_FMT <vidioc_enum_fmt>` ioctl logic
>   *	for Software Defined Radio output
> + * @vidioc_enum_fmt_meta_cap: pointer to the function that implements
> + *	:ref:`VIDIOC_ENUM_FMT <vidioc_enum_fmt>` ioctl logic
> + *	for metadata capture
>   * @vidioc_g_fmt_vid_cap: pointer to the function that implements
>   *	:ref:`VIDIOC_G_FMT <vidioc_g_fmt>` ioctl logic for video capture
>   *	in single plane mode
> @@ -73,6 +76,8 @@ struct v4l2_fh;
>   * @vidioc_g_fmt_sdr_out: pointer to the function that implements
>   *	:ref:`VIDIOC_G_FMT <vidioc_g_fmt>` ioctl logic for Software Defined
>   *	Radio output
> + * @vidioc_g_fmt_meta_cap: pointer to the function that implements
> + *	:ref:`VIDIOC_G_FMT <vidioc_g_fmt>` ioctl logic for metadata capture
>   * @vidioc_s_fmt_vid_cap: pointer to the function that implements
>   *	:ref:`VIDIOC_S_FMT <vidioc_g_fmt>` ioctl logic for video capture
>   *	in single plane mode
> @@ -103,6 +108,8 @@ struct v4l2_fh;
>   * @vidioc_s_fmt_sdr_out: pointer to the function that implements
>   *	:ref:`VIDIOC_S_FMT <vidioc_g_fmt>` ioctl logic for Software Defined
>   *	Radio output
> + * @vidioc_s_fmt_meta_cap: pointer to the function that implements
> + *	:ref:`VIDIOC_S_FMT <vidioc_g_fmt>` ioctl logic for metadata capture
>   * @vidioc_try_fmt_vid_cap: pointer to the function that implements
>   *	:ref:`VIDIOC_TRY_FMT <vidioc_g_fmt>` ioctl logic for video capture
>   *	in single plane mode
> @@ -135,6 +142,8 @@ struct v4l2_fh;
>   * @vidioc_try_fmt_sdr_out: pointer to the function that implements
>   *	:ref:`VIDIOC_TRY_FMT <vidioc_g_fmt>` ioctl logic for Software Defined
>   *	Radio output
> + * @vidioc_try_fmt_meta_cap: pointer to the function that implements
> + *	:ref:`VIDIOC_TRY_FMT <vidioc_g_fmt>` ioctl logic for metadata capture
>   * @vidioc_reqbufs: pointer to the function that implements
>   *	:ref:`VIDIOC_REQBUFS <vidioc_reqbufs>` ioctl
>   * @vidioc_querybuf: pointer to the function that implements
> @@ -304,6 +313,8 @@ struct v4l2_ioctl_ops {
>  					    struct v4l2_fmtdesc *f);
>  	int (*vidioc_enum_fmt_sdr_out)     (struct file *file, void *fh,
>  					    struct v4l2_fmtdesc *f);
> +	int (*vidioc_enum_fmt_meta_cap)    (struct file *file, void *fh,
> +					    struct v4l2_fmtdesc *f);
>  
>  	/* VIDIOC_G_FMT handlers */
>  	int (*vidioc_g_fmt_vid_cap)    (struct file *file, void *fh,
> @@ -330,6 +341,8 @@ struct v4l2_ioctl_ops {
>  					struct v4l2_format *f);
>  	int (*vidioc_g_fmt_sdr_out)    (struct file *file, void *fh,
>  					struct v4l2_format *f);
> +	int (*vidioc_g_fmt_meta_cap)   (struct file *file, void *fh,
> +					struct v4l2_format *f);
>  
>  	/* VIDIOC_S_FMT handlers */
>  	int (*vidioc_s_fmt_vid_cap)    (struct file *file, void *fh,
> @@ -356,6 +369,8 @@ struct v4l2_ioctl_ops {
>  					struct v4l2_format *f);
>  	int (*vidioc_s_fmt_sdr_out)    (struct file *file, void *fh,
>  					struct v4l2_format *f);
> +	int (*vidioc_s_fmt_meta_cap)   (struct file *file, void *fh,
> +					struct v4l2_format *f);
>  
>  	/* VIDIOC_TRY_FMT handlers */
>  	int (*vidioc_try_fmt_vid_cap)    (struct file *file, void *fh,
> @@ -382,6 +397,8 @@ struct v4l2_ioctl_ops {
>  					  struct v4l2_format *f);
>  	int (*vidioc_try_fmt_sdr_out)    (struct file *file, void *fh,
>  					  struct v4l2_format *f);
> +	int (*vidioc_try_fmt_meta_cap)   (struct file *file, void *fh,
> +					  struct v4l2_format *f);
>  
>  	/* Buffer handlers */
>  	int (*vidioc_reqbufs) (struct file *file, void *fh, struct v4l2_requestbuffers *b);
> diff --git a/include/trace/events/v4l2.h b/include/trace/events/v4l2.h
> index ee7754c6e4a1..b3a85b3df53e 100644
> --- a/include/trace/events/v4l2.h
> +++ b/include/trace/events/v4l2.h
> @@ -29,6 +29,7 @@
>  	EM( V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,  "VIDEO_OUTPUT_MPLANE" )	\
>  	EM( V4L2_BUF_TYPE_SDR_CAPTURE,          "SDR_CAPTURE" )		\
>  	EM( V4L2_BUF_TYPE_SDR_OUTPUT,           "SDR_OUTPUT" )		\
> +	EM( V4L2_BUF_TYPE_META_CAPTURE,		"META_CAPTURE" )	\
>  	EMe(V4L2_BUF_TYPE_PRIVATE,		"PRIVATE" )
>  
>  SHOW_TYPE
> diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
> index 724f43e69d03..e0afe68f24ee 100644
> --- a/include/uapi/linux/videodev2.h
> +++ b/include/uapi/linux/videodev2.h
> @@ -143,6 +143,7 @@ enum v4l2_buf_type {
>  	V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE  = 10,
>  	V4L2_BUF_TYPE_SDR_CAPTURE          = 11,
>  	V4L2_BUF_TYPE_SDR_OUTPUT           = 12,
> +	V4L2_BUF_TYPE_META_CAPTURE         = 13,
>  	/* Deprecated, do not use */
>  	V4L2_BUF_TYPE_PRIVATE              = 0x80,
>  };
> @@ -435,6 +436,7 @@ struct v4l2_capability {
>  #define V4L2_CAP_SDR_CAPTURE		0x00100000  /* Is a SDR capture device */
>  #define V4L2_CAP_EXT_PIX_FORMAT		0x00200000  /* Supports the extended pixel format */
>  #define V4L2_CAP_SDR_OUTPUT		0x00400000  /* Is a SDR output device */
> +#define V4L2_CAP_META_CAPTURE		0x00800000  /* Is a metadata capture device */
>  
>  #define V4L2_CAP_READWRITE              0x01000000  /* read/write systemcalls */
>  #define V4L2_CAP_ASYNCIO                0x02000000  /* async I/O */
> @@ -2002,6 +2004,16 @@ struct v4l2_sdr_format {
>  } __attribute__ ((packed));
>  
>  /**
> + * struct v4l2_meta_format - metadata format definition
> + * @dataformat:		little endian four character code (fourcc)
> + * @buffersize:		maximum size in bytes required for data
> + */
> +struct v4l2_meta_format {
> +	__u32				dataformat;
> +	__u32				buffersize;
> +} __attribute__ ((packed));
> +
> +/**
>   * struct v4l2_format - stream data format
>   * @type:	enum v4l2_buf_type; type of the data stream
>   * @pix:	definition of an image format
> @@ -2020,6 +2032,7 @@ struct v4l2_format {
>  		struct v4l2_vbi_format		vbi;     /* V4L2_BUF_TYPE_VBI_CAPTURE */
>  		struct v4l2_sliced_vbi_format	sliced;  /* V4L2_BUF_TYPE_SLICED_VBI_CAPTURE */
>  		struct v4l2_sdr_format		sdr;     /* V4L2_BUF_TYPE_SDR_CAPTURE */
> +		struct v4l2_meta_format		meta;    /* V4L2_BUF_TYPE_META_CAPTURE */
>  		__u8	raw_data[200];                   /* user-defined */
>  	} fmt;
>  };
> 

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v2 2/4] v4l: Define a pixel format for the R-Car VSP1 1-D histogram engine
  2016-08-17 12:20 ` [PATCH v2 2/4] v4l: Define a pixel format for the R-Car VSP1 1-D histogram engine Laurent Pinchart
@ 2016-09-06 17:06   ` Mauro Carvalho Chehab
  2016-09-06 18:11     ` Laurent Pinchart
  0 siblings, 1 reply; 17+ messages in thread
From: Mauro Carvalho Chehab @ 2016-09-06 17:06 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media, linux-renesas-soc
  Cc: Sakari Ailus, Hans Verkuil, Guennadi Liakhovetski

Hi Laurent,

Em Wed, 17 Aug 2016 15:20:28 +0300
Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> escreveu:

> The format is used on the R-Car VSP1 video queues that carry
> 1-D histogram statistics data.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> ---
> Changes since v1:
> 
> - Rebased on top of the DocBook to reST conversion
> 
>  Documentation/media/uapi/v4l/meta-formats.rst      |  15 ++
>  .../media/uapi/v4l/pixfmt-meta-vsp1-hgo.rst        | 170 +++++++++++++++++++++
>  Documentation/media/uapi/v4l/pixfmt.rst            |   1 +
>  drivers/media/v4l2-core/v4l2-ioctl.c               |   1 +
>  include/uapi/linux/videodev2.h                     |   3 +
>  5 files changed, 190 insertions(+)
>  create mode 100644 Documentation/media/uapi/v4l/meta-formats.rst
>  create mode 100644 Documentation/media/uapi/v4l/pixfmt-meta-vsp1-hgo.rst
> 
> diff --git a/Documentation/media/uapi/v4l/meta-formats.rst b/Documentation/media/uapi/v4l/meta-formats.rst
> new file mode 100644
> index 000000000000..05ab91e12f10
> --- /dev/null
> +++ b/Documentation/media/uapi/v4l/meta-formats.rst
> @@ -0,0 +1,15 @@
> +.. -*- coding: utf-8; mode: rst -*-
> +
> +.. _meta-formats:
> +
> +****************
> +Metadata Formats
> +****************
> +
> +These formats are used for the :ref:`metadata` interface only.
> +
> +
> +.. toctree::
> +    :maxdepth: 1
> +
> +    pixfmt-meta-vsp1-hgo
> diff --git a/Documentation/media/uapi/v4l/pixfmt-meta-vsp1-hgo.rst b/Documentation/media/uapi/v4l/pixfmt-meta-vsp1-hgo.rst
> new file mode 100644
> index 000000000000..e935e4525b10
> --- /dev/null
> +++ b/Documentation/media/uapi/v4l/pixfmt-meta-vsp1-hgo.rst
> @@ -0,0 +1,170 @@
> +.. -*- coding: utf-8; mode: rst -*-
> +
> +.. _v4l2-meta-fmt-vsp1-hgo:
> +
> +*******************************
> +V4L2_META_FMT_VSP1_HGO ('VSPH')
> +*******************************
> +
> +*man V4L2_META_FMT_VSP1_HGO(2)*

Just remove it. This is some trash that came from the conversions.
I have a set of patches removing it on the existing man pages.

> +
> +Renesas R-Car VSP1 1-D Histogram Data
> +
> +
> +Description
> +===========
> +
> +This format describes histogram data generated by the Renesas R-Car VSP1 1-D
> +Histogram (HGO) engine.
> +
> +The VSP1 HGO is a histogram computation engine that can operate on RGB, YCrCb
> +or HSV data. It operates on a possibly cropped and subsampled input image and
> +computes the minimum, maximum and sum of all pixels as well as per-channel
> +histograms.
> +
> +The HGO can compute histograms independently per channel, on the maximum of the
> +three channels (RGB data only) or on the Y channel only (YCbCr only). It can
> +additionally output the histogram with 64 or 256 bins, resulting in four
> +possible modes of operation.
> +
> +- In *64 bins normal mode*, the HGO operates on the three channels independently
> +  to compute three 64-bins histograms. RGB, YCbCr and HSV image formats are
> +  supported.
> +- In *64 bins maximum mode*, the HGO operates on the maximum of the (R, G, B)
> +  channels to compute a single 64-bins histogram. Only the RGB image format is
> +  supported.
> +- In *256 bins normal mode*, the HGO operates on the Y channel to compute a
> +  single 256-bins histogram. Only the YCbCr image format is supported.
> +- In *256 bins maximum mode*, the HGO operates on the maximum of the (R, G, B)
> +  channels to compute a single 256-bins histogram. Only the RGB image format is
> +  supported.

As they all share the same FOURCC format, according with the documentation,
how the user is supposed to switch between those modes? Or is it depend on
the video format? In any case, please add some explanation, and cross-refs
if needed.

> +
> +**Byte Order.**
> +All data is stored in memory in little endian format. Each cell in the tables
> +contains one byte.
> +
> +.. flat-table:: VSP1 HGO Data - 64 Bins, Normal Mode (792 bytes)
> +    :header-rows:  2
> +    :stub-columns: 0
> +
> +    * - Offset
> +      - :cspan:`4` Memory
> +    * -
> +      - [31:24]
> +      - [23:16]
> +      - [15:8]
> +      - [7:0]
> +    * - 0
> +      - -
> +      - R/Cr/H max [7:0]
> +      - -
> +      - R/Cr/H min [7:0]
> +    * - 4
> +      - -
> +      - G/Y/S max [7:0]
> +      - -
> +      - G/Y/S min [7:0]
> +    * - 8
> +      - -
> +      - B/Cb/V max [7:0]
> +      - -
> +      - B/Cb/V min [7:0]
> +    * - 12
> +      - :cspan:`4` R/Cr/H sum [31:0]
> +    * - 16
> +      - :cspan:`4` G/Y/S sum [31:0]
> +    * - 20
> +      - :cspan:`4` B/Cb/V sum [31:0]
> +    * - 24
> +      - :cspan:`4` R/Cr/H bin 0 [31:0]
> +    * -
> +      - :cspan:`4` ...
> +    * - 276
> +      - :cspan:`4` R/Cr/H bin 63 [31:0]
> +    * - 280
> +      - :cspan:`4` G/Y/S bin 0 [31:0]
> +    * -
> +      - :cspan:`4` ...
> +    * - 532
> +      - :cspan:`4` G/Y/S bin 63 [31:0]
> +    * - 536
> +      - :cspan:`4` B/Cb/V bin 0 [31:0]
> +    * -
> +      - :cspan:`4` ...
> +    * - 788
> +      - :cspan:`4` B/Cb/V bin 63 [31:0]
> +
> +.. flat-table:: VSP1 HGO Data - 64 Bins, Max Mode (264 bytes)
> +    :header-rows:  2
> +    :stub-columns: 0
> +
> +    * - Offset
> +      - :cspan:`4` Memory
> +    * -
> +      - [31:24]
> +      - [23:16]
> +      - [15:8]
> +      - [7:0]
> +    * - 0
> +      - -
> +      - max(R,G,B) max [7:0]
> +      - -
> +      - max(R,G,B) min [7:0]
> +    * - 4
> +      - :cspan:`4` max(R,G,B) sum [31:0]
> +    * - 8
> +      - :cspan:`4` max(R,G,B) bin 0 [31:0]
> +    * -
> +      - :cspan:`4` ...
> +    * - 260
> +      - :cspan:`4` max(R,G,B) bin 63 [31:0]
> +
> +.. flat-table:: VSP1 HGO Data - 256 Bins, Normal Mode (1032 bytes)
> +    :header-rows:  2
> +    :stub-columns: 0
> +
> +    * - Offset
> +      - :cspan:`4` Memory
> +    * -
> +      - [31:24]
> +      - [23:16]
> +      - [15:8]
> +      - [7:0]
> +    * - 0
> +      - -
> +      - Y max [7:0]
> +      - -
> +      - Y min [7:0]
> +    * - 4
> +      - :cspan:`4` Y sum [31:0]
> +    * - 8
> +      - :cspan:`4` Y bin 0 [31:0]
> +    * -
> +      - :cspan:`4` ...
> +    * - 1028
> +      - :cspan:`4` Y bin 255 [31:0]
> +
> +.. flat-table:: VSP1 HGO Data - 256 Bins, Max Mode (1032 bytes)
> +    :header-rows:  2
> +    :stub-columns: 0
> +
> +    * - Offset
> +      - :cspan:`4` Memory
> +    * -
> +      - [31:24]
> +      - [23:16]
> +      - [15:8]
> +      - [7:0]
> +    * - 0
> +      - -
> +      - max(R,G,B) max [7:0]
> +      - -
> +      - max(R,G,B) min [7:0]
> +    * - 4
> +      - :cspan:`4` max(R,G,B) sum [31:0]
> +    * - 8
> +      - :cspan:`4` max(R,G,B) bin 0 [31:0]
> +    * -
> +      - :cspan:`4` ...
> +    * - 1028
> +      - :cspan:`4` max(R,G,B) bin 255 [31:0]
> diff --git a/Documentation/media/uapi/v4l/pixfmt.rst b/Documentation/media/uapi/v4l/pixfmt.rst
> index 81222a99f7ce..e3738a2eb05f 100644
> --- a/Documentation/media/uapi/v4l/pixfmt.rst
> +++ b/Documentation/media/uapi/v4l/pixfmt.rst
> @@ -32,4 +32,5 @@ see also :ref:`VIDIOC_G_FBUF <VIDIOC_G_FBUF>`.)
>      depth-formats
>      pixfmt-013
>      sdr-formats
> +    meta-formats
>      pixfmt-reserved
> diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
> index 0afa07bfea35..8425f0b8ebfb 100644
> --- a/drivers/media/v4l2-core/v4l2-ioctl.c
> +++ b/drivers/media/v4l2-core/v4l2-ioctl.c
> @@ -1265,6 +1265,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
>  	case V4L2_SDR_FMT_CS8:		descr = "Complex S8"; break;
>  	case V4L2_SDR_FMT_CS14LE:	descr = "Complex S14LE"; break;
>  	case V4L2_SDR_FMT_RU12LE:	descr = "Real U12LE"; break;
> +	case V4L2_META_FMT_VSP1_HGO:	descr = "R-Car VSP1 1-D Histogram"; break;
>  
>  	default:
>  		/* Compressed formats */
> diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
> index d1ac0250a966..05b97c2067d4 100644
> --- a/include/uapi/linux/videodev2.h
> +++ b/include/uapi/linux/videodev2.h
> @@ -637,6 +637,9 @@ struct v4l2_pix_format {
>  #define V4L2_SDR_FMT_CS14LE       v4l2_fourcc('C', 'S', '1', '4') /* complex s14le */
>  #define V4L2_SDR_FMT_RU12LE       v4l2_fourcc('R', 'U', '1', '2') /* real u12le */
>  
> +/* Meta-data formats */
> +#define V4L2_META_FMT_VSP1_HGO    v4l2_fourcc('V', 'S', 'P', 'H') /* R-Car VSP1 Histogram */
> +
>  /* priv field value to indicates that subsequent fields are valid. */
>  #define V4L2_PIX_FMT_PRIV_MAGIC		0xfeedcafe
>  



Thanks,
Mauro

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v2 2/4] v4l: Define a pixel format for the R-Car VSP1 1-D histogram engine
  2016-09-06 17:06   ` Mauro Carvalho Chehab
@ 2016-09-06 18:11     ` Laurent Pinchart
  2016-09-06 18:21       ` Mauro Carvalho Chehab
  0 siblings, 1 reply; 17+ messages in thread
From: Laurent Pinchart @ 2016-09-06 18:11 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Laurent Pinchart, linux-media, linux-renesas-soc, Sakari Ailus,
	Hans Verkuil, Guennadi Liakhovetski

Hi Mauro,

On Tuesday 06 Sep 2016 14:06:51 Mauro Carvalho Chehab wrote:
> Em Wed, 17 Aug 2016 15:20:28 +0300 Laurent Pinchart escreveu:
> > The format is used on the R-Car VSP1 video queues that carry
> > 1-D histogram statistics data.
> > 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> > Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> > ---
> > Changes since v1:
> > 
> > - Rebased on top of the DocBook to reST conversion
> > 
> >  Documentation/media/uapi/v4l/meta-formats.rst      |  15 ++
> >  .../media/uapi/v4l/pixfmt-meta-vsp1-hgo.rst        | 170 ++++++++++++++++
> >  Documentation/media/uapi/v4l/pixfmt.rst            |   1 +
> >  drivers/media/v4l2-core/v4l2-ioctl.c               |   1 +
> >  include/uapi/linux/videodev2.h                     |   3 +
> >  5 files changed, 190 insertions(+)
> >  create mode 100644 Documentation/media/uapi/v4l/meta-formats.rst
> >  create mode 100644 Documentation/media/uapi/v4l/pixfmt-meta-vsp1-hgo.rst
> > 
> > diff --git a/Documentation/media/uapi/v4l/meta-formats.rst
> > b/Documentation/media/uapi/v4l/meta-formats.rst new file mode 100644
> > index 000000000000..05ab91e12f10
> > --- /dev/null
> > +++ b/Documentation/media/uapi/v4l/meta-formats.rst
> > @@ -0,0 +1,15 @@
> > +.. -*- coding: utf-8; mode: rst -*-
> > +
> > +.. _meta-formats:
> > +
> > +****************
> > +Metadata Formats
> > +****************
> > +
> > +These formats are used for the :ref:`metadata` interface only.
> > +
> > +
> > +.. toctree::
> > +    :maxdepth: 1
> > +
> > +    pixfmt-meta-vsp1-hgo
> > diff --git a/Documentation/media/uapi/v4l/pixfmt-meta-vsp1-hgo.rst
> > b/Documentation/media/uapi/v4l/pixfmt-meta-vsp1-hgo.rst new file mode
> > 100644
> > index 000000000000..e935e4525b10
> > --- /dev/null
> > +++ b/Documentation/media/uapi/v4l/pixfmt-meta-vsp1-hgo.rst
> > @@ -0,0 +1,170 @@
> > +.. -*- coding: utf-8; mode: rst -*-
> > +
> > +.. _v4l2-meta-fmt-vsp1-hgo:
> > +
> > +*******************************
> > +V4L2_META_FMT_VSP1_HGO ('VSPH')
> > +*******************************
> > +
> > +*man V4L2_META_FMT_VSP1_HGO(2)*
> 
> Just remove it. This is some trash that came from the conversions.
> I have a set of patches removing it on the existing man pages.

Sure, I will do.

> > +
> > +Renesas R-Car VSP1 1-D Histogram Data
> > +
> > +
> > +Description
> > +===========
> > +
> > +This format describes histogram data generated by the Renesas R-Car VSP1
> > 1-D +Histogram (HGO) engine.
> > +
> > +The VSP1 HGO is a histogram computation engine that can operate on RGB,
> > YCrCb +or HSV data. It operates on a possibly cropped and subsampled
> > input image and +computes the minimum, maximum and sum of all pixels as
> > well as per-channel +histograms.
> > +
> > +The HGO can compute histograms independently per channel, on the maximum
> > of the +three channels (RGB data only) or on the Y channel only (YCbCr
> > only). It can +additionally output the histogram with 64 or 256 bins,
> > resulting in four +possible modes of operation.
> > +
> > +- In *64 bins normal mode*, the HGO operates on the three channels
> > independently +  to compute three 64-bins histograms. RGB, YCbCr and HSV
> > image formats are +  supported.
> > +- In *64 bins maximum mode*, the HGO operates on the maximum of the (R,
> > G, B) +  channels to compute a single 64-bins histogram. Only the RGB
> > image format is +  supported.
> > +- In *256 bins normal mode*, the HGO operates on the Y channel to compute
> > a +  single 256-bins histogram. Only the YCbCr image format is supported.
> > +- In *256 bins maximum mode*, the HGO operates on the maximum of the (R,
> > G, B) +  channels to compute a single 256-bins histogram. Only the RGB
> > image format is +  supported.
> 
> As they all share the same FOURCC format, according with the documentation,
> how the user is supposed to switch between those modes? Or is it depend on
> the video format? In any case, please add some explanation, and cross-refs
> if needed.

The modes are selected using controls, they don't depend on the video format. 
Do you think it would make sense to cross-reference between formats and 
controls ?

[snip]

-- 
Regards,

Laurent Pinchart


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v2 2/4] v4l: Define a pixel format for the R-Car VSP1 1-D histogram engine
  2016-09-06 18:11     ` Laurent Pinchart
@ 2016-09-06 18:21       ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 17+ messages in thread
From: Mauro Carvalho Chehab @ 2016-09-06 18:21 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Laurent Pinchart, linux-media, linux-renesas-soc, Sakari Ailus,
	Hans Verkuil, Guennadi Liakhovetski

Em Tue, 06 Sep 2016 21:11:10 +0300
Laurent Pinchart <laurent.pinchart@ideasonboard.com> escreveu:

> Hi Mauro,
> 
> On Tuesday 06 Sep 2016 14:06:51 Mauro Carvalho Chehab wrote:
> > Em Wed, 17 Aug 2016 15:20:28 +0300 Laurent Pinchart escreveu:  
> > > The format is used on the R-Car VSP1 video queues that carry
> > > 1-D histogram statistics data.
> > > 
> > > Signed-off-by: Laurent Pinchart
> > > <laurent.pinchart+renesas@ideasonboard.com>
> > > Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> > > ---
> > > Changes since v1:
> > > 
> > > - Rebased on top of the DocBook to reST conversion
> > > 
> > >  Documentation/media/uapi/v4l/meta-formats.rst      |  15 ++
> > >  .../media/uapi/v4l/pixfmt-meta-vsp1-hgo.rst        | 170 ++++++++++++++++
> > >  Documentation/media/uapi/v4l/pixfmt.rst            |   1 +
> > >  drivers/media/v4l2-core/v4l2-ioctl.c               |   1 +
> > >  include/uapi/linux/videodev2.h                     |   3 +
> > >  5 files changed, 190 insertions(+)
> > >  create mode 100644 Documentation/media/uapi/v4l/meta-formats.rst
> > >  create mode 100644 Documentation/media/uapi/v4l/pixfmt-meta-vsp1-hgo.rst
> > > 
> > > diff --git a/Documentation/media/uapi/v4l/meta-formats.rst
> > > b/Documentation/media/uapi/v4l/meta-formats.rst new file mode 100644
> > > index 000000000000..05ab91e12f10
> > > --- /dev/null
> > > +++ b/Documentation/media/uapi/v4l/meta-formats.rst
> > > @@ -0,0 +1,15 @@
> > > +.. -*- coding: utf-8; mode: rst -*-
> > > +
> > > +.. _meta-formats:
> > > +
> > > +****************
> > > +Metadata Formats
> > > +****************
> > > +
> > > +These formats are used for the :ref:`metadata` interface only.
> > > +
> > > +
> > > +.. toctree::
> > > +    :maxdepth: 1
> > > +
> > > +    pixfmt-meta-vsp1-hgo
> > > diff --git a/Documentation/media/uapi/v4l/pixfmt-meta-vsp1-hgo.rst
> > > b/Documentation/media/uapi/v4l/pixfmt-meta-vsp1-hgo.rst new file mode
> > > 100644
> > > index 000000000000..e935e4525b10
> > > --- /dev/null
> > > +++ b/Documentation/media/uapi/v4l/pixfmt-meta-vsp1-hgo.rst
> > > @@ -0,0 +1,170 @@
> > > +.. -*- coding: utf-8; mode: rst -*-
> > > +
> > > +.. _v4l2-meta-fmt-vsp1-hgo:
> > > +
> > > +*******************************
> > > +V4L2_META_FMT_VSP1_HGO ('VSPH')
> > > +*******************************
> > > +
> > > +*man V4L2_META_FMT_VSP1_HGO(2)*  
> > 
> > Just remove it. This is some trash that came from the conversions.
> > I have a set of patches removing it on the existing man pages.  
> 
> Sure, I will do.

Thanks!

> > > +
> > > +Renesas R-Car VSP1 1-D Histogram Data
> > > +
> > > +
> > > +Description
> > > +===========
> > > +
> > > +This format describes histogram data generated by the Renesas R-Car VSP1
> > > 1-D +Histogram (HGO) engine.
> > > +
> > > +The VSP1 HGO is a histogram computation engine that can operate on RGB,
> > > YCrCb +or HSV data. It operates on a possibly cropped and subsampled
> > > input image and +computes the minimum, maximum and sum of all pixels as
> > > well as per-channel +histograms.
> > > +
> > > +The HGO can compute histograms independently per channel, on the maximum
> > > of the +three channels (RGB data only) or on the Y channel only (YCbCr
> > > only). It can +additionally output the histogram with 64 or 256 bins,
> > > resulting in four +possible modes of operation.
> > > +
> > > +- In *64 bins normal mode*, the HGO operates on the three channels
> > > independently +  to compute three 64-bins histograms. RGB, YCbCr and HSV
> > > image formats are +  supported.
> > > +- In *64 bins maximum mode*, the HGO operates on the maximum of the (R,
> > > G, B) +  channels to compute a single 64-bins histogram. Only the RGB
> > > image format is +  supported.
> > > +- In *256 bins normal mode*, the HGO operates on the Y channel to compute
> > > a +  single 256-bins histogram. Only the YCbCr image format is supported.
> > > +- In *256 bins maximum mode*, the HGO operates on the maximum of the (R,
> > > G, B) +  channels to compute a single 256-bins histogram. Only the RGB
> > > image format is +  supported.  
> > 
> > As they all share the same FOURCC format, according with the documentation,
> > how the user is supposed to switch between those modes? Or is it depend on
> > the video format? In any case, please add some explanation, and cross-refs
> > if needed.  
> 
> The modes are selected using controls, they don't depend on the video format. 
> Do you think it would make sense to cross-reference between formats and 
> controls ?

It probably makes a way more sense to use enum_fmt/s_fmt/g_fmt ioctls and
add one different fourcc per format.

Using a control instead of *fmt to select the format seems really weird,
as it is not what it is expected for the fourcc formats.


Thanks,
Mauro

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v2 0/4] R-Car VSP1 1-D Histogram support
  2016-08-17 12:20 [PATCH v2 0/4] R-Car VSP1 1-D Histogram support Laurent Pinchart
                   ` (4 preceding siblings ...)
  2016-09-05  8:08 ` [PATCH v2.2 1/4] v4l: Add metadata buffer type and format Laurent Pinchart
@ 2016-09-13 12:19 ` Geert Uytterhoeven
  2016-09-13 14:04   ` Laurent Pinchart
  5 siblings, 1 reply; 17+ messages in thread
From: Geert Uytterhoeven @ 2016-09-13 12:19 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Linux Media Mailing List, Linux-Renesas, Sakari Ailus,
	Hans Verkuil, Guennadi Liakhovetski

Hi Laurent,

On Wed, Aug 17, 2016 at 2:20 PM, Laurent Pinchart
<laurent.pinchart+renesas@ideasonboard.com> wrote:
> This patch series implements support for the Renesas R-Car VSP1 1-D histogram
> generator (HGO). It is based on top of the latest media tree's master branch,
> and available for convenience at
>
>         git://linuxtv.org/pinchartl/media.git vsp1/hgo

I've dropped the above branch from today's renesas-drivers release due to too
many merge conflicts.

Thanks for your understanding.

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v2 0/4] R-Car VSP1 1-D Histogram support
  2016-09-13 12:19 ` [PATCH v2 0/4] R-Car VSP1 1-D Histogram support Geert Uytterhoeven
@ 2016-09-13 14:04   ` Laurent Pinchart
  0 siblings, 0 replies; 17+ messages in thread
From: Laurent Pinchart @ 2016-09-13 14:04 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Laurent Pinchart, Linux Media Mailing List, Linux-Renesas,
	Sakari Ailus, Hans Verkuil, Guennadi Liakhovetski

Hi Geert,

On Tuesday 13 Sep 2016 14:19:56 Geert Uytterhoeven wrote:
> On Wed, Aug 17, 2016 at 2:20 PM, Laurent Pinchart wrote:
> > This patch series implements support for the Renesas R-Car VSP1 1-D
> > histogram generator (HGO). It is based on top of the latest media tree's
> > master branch, and available for convenience at
> > 
> >         git://linuxtv.org/pinchartl/media.git vsp1/hgo
> 
> I've dropped the above branch from today's renesas-drivers release due to
> too many merge conflicts.

No worries. I'll submit a rebased version soon.

-- 
Regards,

Laurent Pinchart


^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2016-09-13 14:03 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-08-17 12:20 [PATCH v2 0/4] R-Car VSP1 1-D Histogram support Laurent Pinchart
2016-08-17 12:20 ` [PATCH v2 1/4] v4l: Add metadata buffer type and format Laurent Pinchart
2016-08-29  9:13   ` Sakari Ailus
2016-09-01 21:22     ` Laurent Pinchart
2016-09-01 21:40       ` Laurent Pinchart
2016-09-02  8:18         ` Sakari Ailus
2016-09-02  7:31       ` Sakari Ailus
2016-08-17 12:20 ` [PATCH v2 2/4] v4l: Define a pixel format for the R-Car VSP1 1-D histogram engine Laurent Pinchart
2016-09-06 17:06   ` Mauro Carvalho Chehab
2016-09-06 18:11     ` Laurent Pinchart
2016-09-06 18:21       ` Mauro Carvalho Chehab
2016-08-17 12:20 ` [PATCH v2 3/4] v4l: vsp1: Add HGO support Laurent Pinchart
2016-08-17 12:20 ` [PATCH v2 4/4] v4l: vsp1: Don't create HGO entity when the userspace API is disabled Laurent Pinchart
2016-09-05  8:08 ` [PATCH v2.2 1/4] v4l: Add metadata buffer type and format Laurent Pinchart
2016-09-05  8:10   ` Hans Verkuil
2016-09-13 12:19 ` [PATCH v2 0/4] R-Car VSP1 1-D Histogram support Geert Uytterhoeven
2016-09-13 14:04   ` Laurent Pinchart

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.