The metadata video device is used to transfer metadata between
userspace and kernelspace. It supports the metadata buffer type only.

Signed-off-by: Laurent Pinchart <laurent.pinchart+rene...@ideasonboard.com>
---
 Documentation/DocBook/media/v4l/dev-meta.xml | 10 +++++++---
 drivers/media/v4l2-core/v4l2-dev.c           | 21 ++++++++++++++++++++-
 drivers/media/v4l2-core/v4l2-ioctl.c         | 15 ++++++++++-----
 include/media/v4l2-dev.h                     |  3 ++-
 include/uapi/linux/media.h                   |  2 ++
 5 files changed, 41 insertions(+), 10 deletions(-)

diff --git a/Documentation/DocBook/media/v4l/dev-meta.xml 
b/Documentation/DocBook/media/v4l/dev-meta.xml
index 9b5b1fba2007..75bd22521af7 100644
--- a/Documentation/DocBook/media/v4l/dev-meta.xml
+++ b/Documentation/DocBook/media/v4l/dev-meta.xml
@@ -14,9 +14,13 @@ intended for transfer of metadata to userspace and control 
of that operation.
   </para>
 
   <para>
-The metadata interface is implemented on video capture devices. The device can
-be dedicated to metadata or can implement both video and metadata capture as
-specified in its reported capabilities.
+The metadata interface can be implemented on video capture devices, metadata
+devices or both, at the discretion of drivers. Metadata devices are accessed
+through character device special files named
+<filename>/dev/v4l-meta[0-9]+</filename> with major number 81 and dynamically
+allocated minor numbers. Video devices that support metadata capture can be
+dedicated to metadata or can implement both metadata capture and video capture
+and/or output, as specified in the device's reported capabilities.
   </para>
 
   <section>
diff --git a/drivers/media/v4l2-core/v4l2-dev.c 
b/drivers/media/v4l2-core/v4l2-dev.c
index 74b79e60ac38..5a8d7b03ab97 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -527,6 +527,7 @@ static void determine_valid_ioctls(struct video_device 
*vdev)
        bool is_vbi = vdev->vfl_type == VFL_TYPE_VBI;
        bool is_radio = vdev->vfl_type == VFL_TYPE_RADIO;
        bool is_sdr = vdev->vfl_type == VFL_TYPE_SDR;
+       bool is_meta = vdev->vfl_type == VFL_TYPE_META;
        bool is_rx = vdev->vfl_dir != VFL_DIR_TX;
        bool is_tx = vdev->vfl_dir != VFL_DIR_RX;
 
@@ -664,9 +665,18 @@ static void determine_valid_ioctls(struct video_device 
*vdev)
                        set_bit(_IOC_NR(VIDIOC_S_FMT), valid_ioctls);
                if (ops->vidioc_try_fmt_sdr_out)
                        set_bit(_IOC_NR(VIDIOC_TRY_FMT), valid_ioctls);
+       } else if (is_meta && is_rx) {
+               if (ops->vidioc_enum_fmt_meta_cap)
+                       set_bit(_IOC_NR(VIDIOC_ENUM_FMT), valid_ioctls);
+               if (ops->vidioc_g_fmt_meta_cap)
+                       set_bit(_IOC_NR(VIDIOC_G_FMT), valid_ioctls);
+               if (ops->vidioc_s_fmt_meta_cap)
+                       set_bit(_IOC_NR(VIDIOC_S_FMT), valid_ioctls);
+               if (ops->vidioc_try_fmt_meta_cap)
+                       set_bit(_IOC_NR(VIDIOC_TRY_FMT), valid_ioctls);
        }
 
-       if (is_vid || is_vbi || is_sdr) {
+       if (is_vid || is_vbi || is_sdr || is_meta) {
                /* ioctls valid for video, metadata, vbi or sdr */
                SET_VALID_IOCTL(ops, VIDIOC_REQBUFS, vidioc_reqbufs);
                SET_VALID_IOCTL(ops, VIDIOC_QUERYBUF, vidioc_querybuf);
@@ -767,6 +777,10 @@ static int video_register_media_controller(struct 
video_device *vdev, int type)
                intf_type = MEDIA_INTF_T_V4L_SUBDEV;
                /* Entity will be created via v4l2_device_register_subdev() */
                break;
+       case VFL_TYPE_META:
+               intf_type = MEDIA_INTF_T_V4L_META;
+               vdev->entity.function = MEDIA_ENT_F_IO_META;
+               break;
        default:
                return 0;
        }
@@ -849,6 +863,8 @@ static int video_register_media_controller(struct 
video_device *vdev, int type)
  *     %VFL_TYPE_SUBDEV - A subdevice
  *
  *     %VFL_TYPE_SDR - Software Defined Radio
+ *
+ *     %VFL_TYPE_META - Metadata
  */
 int __video_register_device(struct video_device *vdev, int type, int nr,
                int warn_if_nr_in_use, struct module *owner)
@@ -892,6 +908,9 @@ int __video_register_device(struct video_device *vdev, int 
type, int nr,
                /* Use device name 'swradio' because 'sdr' was already taken. */
                name_base = "swradio";
                break;
+       case VFL_TYPE_META:
+               name_base = "v4l-meta";
+               break;
        default:
                printk(KERN_ERR "%s called with unknown type: %d\n",
                       __func__, type);
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c 
b/drivers/media/v4l2-core/v4l2-ioctl.c
index 5d003152ff68..256938fff9e0 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -935,6 +935,7 @@ static int check_fmt(struct file *file, enum v4l2_buf_type 
type)
        bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
        bool is_vbi = vfd->vfl_type == VFL_TYPE_VBI;
        bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
+       bool is_meta = vfd->vfl_type == VFL_TYPE_META;
        bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
        bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
 
@@ -993,7 +994,7 @@ static int check_fmt(struct file *file, enum v4l2_buf_type 
type)
                        return 0;
                break;
        case V4L2_BUF_TYPE_META_CAPTURE:
-               if (is_vid && is_rx && ops->vidioc_g_fmt_meta_cap)
+               if ((is_vid || is_meta) && is_rx && ops->vidioc_g_fmt_meta_cap)
                        return 0;
                break;
        default:
@@ -1324,6 +1325,7 @@ static int v4l_enum_fmt(const struct v4l2_ioctl_ops *ops,
        struct video_device *vfd = video_devdata(file);
        bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
        bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
+       bool is_meta = vfd->vfl_type == VFL_TYPE_META;
        bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
        bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
        int ret = -EINVAL;
@@ -1365,7 +1367,7 @@ static int v4l_enum_fmt(const struct v4l2_ioctl_ops *ops,
                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))
+               if (unlikely(!is_rx || !(is_vid || is_meta) || 
!ops->vidioc_enum_fmt_meta_cap))
                        break;
                ret = ops->vidioc_enum_fmt_meta_cap(file, fh, arg);
                break;
@@ -1382,6 +1384,7 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops,
        struct video_device *vfd = video_devdata(file);
        bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
        bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
+       bool is_meta = vfd->vfl_type == VFL_TYPE_META;
        bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
        bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
        int ret;
@@ -1468,7 +1471,7 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops,
                        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))
+               if (unlikely(!is_rx || !(is_vid || is_meta) || 
!ops->vidioc_g_fmt_meta_cap))
                        break;
                return ops->vidioc_g_fmt_meta_cap(file, fh, arg);
        }
@@ -1482,6 +1485,7 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,
        struct video_device *vfd = video_devdata(file);
        bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
        bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
+       bool is_meta = vfd->vfl_type == VFL_TYPE_META;
        bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
        bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
        int ret;
@@ -1559,7 +1563,7 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,
                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))
+               if (unlikely(!is_rx || !(is_vid || is_meta) || 
!ops->vidioc_s_fmt_meta_cap))
                        break;
                CLEAR_AFTER_FIELD(p, fmt.meta);
                return ops->vidioc_s_fmt_meta_cap(file, fh, arg);
@@ -1574,6 +1578,7 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops,
        struct video_device *vfd = video_devdata(file);
        bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
        bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
+       bool is_meta = vfd->vfl_type == VFL_TYPE_META;
        bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
        bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
        int ret;
@@ -1648,7 +1653,7 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops,
                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))
+               if (unlikely(!is_rx || !(is_vid || is_meta) || 
!ops->vidioc_try_fmt_meta_cap))
                        break;
                CLEAR_AFTER_FIELD(p, fmt.meta);
                return ops->vidioc_try_fmt_meta_cap(file, fh, arg);
diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
index 25a3190308fb..eeab952d4940 100644
--- a/include/media/v4l2-dev.h
+++ b/include/media/v4l2-dev.h
@@ -25,7 +25,8 @@
 #define VFL_TYPE_RADIO         2
 #define VFL_TYPE_SUBDEV                3
 #define VFL_TYPE_SDR           4
-#define VFL_TYPE_MAX           5
+#define VFL_TYPE_META          5
+#define VFL_TYPE_MAX           6
 
 /* Is this a receiver, transmitter or mem-to-mem? */
 /* Ignored for VFL_TYPE_SUBDEV. */
diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h
index df59edee25d1..e226bc35c639 100644
--- a/include/uapi/linux/media.h
+++ b/include/uapi/linux/media.h
@@ -77,6 +77,7 @@ struct media_device_info {
 #define MEDIA_ENT_F_IO_DTV             (MEDIA_ENT_F_BASE + 0x01001)
 #define MEDIA_ENT_F_IO_VBI             (MEDIA_ENT_F_BASE + 0x01002)
 #define MEDIA_ENT_F_IO_SWRADIO         (MEDIA_ENT_F_BASE + 0x01003)
+#define MEDIA_ENT_F_IO_META            (MEDIA_ENT_F_BASE + 0x01004)
 
 /*
  * Analog TV IF-PLL decoders
@@ -297,6 +298,7 @@ struct media_links_enum {
 #define MEDIA_INTF_T_V4L_RADIO  (MEDIA_INTF_T_V4L_BASE + 2)
 #define MEDIA_INTF_T_V4L_SUBDEV (MEDIA_INTF_T_V4L_BASE + 3)
 #define MEDIA_INTF_T_V4L_SWRADIO (MEDIA_INTF_T_V4L_BASE + 4)
+#define MEDIA_INTF_T_V4L_META   (MEDIA_INTF_T_V4L_BASE + 5)
 
 #define MEDIA_INTF_T_ALSA_PCM_CAPTURE   (MEDIA_INTF_T_ALSA_BASE)
 #define MEDIA_INTF_T_ALSA_PCM_PLAYBACK  (MEDIA_INTF_T_ALSA_BASE + 1)
-- 
2.7.3

Reply via email to