Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

media: v4l2: Extend VIDIOC_ENUM_FMT to support MC-centric devices

The VIDIOC_ENUM_FMT ioctl enumerates all formats supported by a video
node. For MC-centric devices, its behaviour has always been ill-defined,
with drivers implementing one of the following behaviours:

- No support for VIDIOC_ENUM_FMT at all
- Enumerating all formats supported by the video node, regardless of the
configuration of the pipeline
- Enumerating formats supported by the video node for the active
configuration of the connected subdevice

The first behaviour is obviously useless for applications. The second
behaviour provides the most information, but doesn't offer a way to find
what formats are compatible with a given pipeline configuration. The
third behaviour fixes that, but with the drawback that applications
can't enumerate all supported formats anymore, and have to modify the
active configuration of the pipeline to enumerate formats.

The situation is messy as none of the implemented behaviours are ideal,
and userspace can't predict what will happen as the behaviour is
driver-specific.

To fix this, let's extend the VIDIOC_ENUM_FMT with a missing capability:
enumerating pixel formats for a given media bus code. The media bus code
is passed through the v4l2_fmtdesc structure in a new mbus_code field
(repurposed from the reserved fields). With this capability in place,
applications can enumerate pixel formats for a given media bus code
without modifying the active configuration of the device.

The current behaviour of the ioctl is preserved when the new mbus_code
field is set to 0, ensuring compatibility with existing userspace. The
API extension is documented as mandatory for MC-centric devices (as
advertised through the V4L2_CAP_IO_MC capability), allowing applications
and compliance tools to easily determine the availability of the
VIDIOC_ENUM_FMT extension.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>

authored by

Laurent Pinchart and committed by
Mauro Carvalho Chehab
e5b6b07a b72f14ee

+34 -7
+21 -4
Documentation/userspace-api/media/v4l/vidioc-enum-fmt.rst
··· 48 48 formats in preference order, where preferred formats are returned before 49 49 (that is, with lower ``index`` value) less-preferred formats. 50 50 51 - .. note:: 51 + If the driver doesn't advertise the ``V4L2_CAP_IO_MC`` :ref:`capability 52 + <device-capabilities>`, applications shall initialize the ``mbus_code`` field 53 + to zero and drivers shall ignore the value of the field. Drivers shall 54 + enumerate all image formats. The enumerated formats may depend on the active 55 + input or output of the device. 52 56 53 - After switching input or output the list of enumerated image 54 - formats may be different. 57 + If the driver advertises the ``V4L2_CAP_IO_MC`` :ref:`capability 58 + <device-capabilities>`, applications may initialize the ``mbus_code`` field to 59 + a valid :ref:`media bus format code <v4l2-mbus-pixelcode>`. If the 60 + ``mbus_code`` field is not zero, drivers shall restrict enumeration to only the 61 + image formats that can produce (for video output devices) or be produced from 62 + (for video capture devices) that media bus code. Regardless of the value of 63 + the ``mbus_code`` field, the enumerated image formats shall not depend on the 64 + active configuration of the video device or device pipeline. Enumeration shall 65 + otherwise operate as previously described. 55 66 56 67 57 68 .. tabularcolumns:: |p{4.4cm}|p{4.4cm}|p{8.7cm}| ··· 117 106 These codes are not the same as those used 118 107 in the Windows world. 119 108 * - __u32 120 - - ``reserved``\ [4] 109 + - ``mbus_code`` 110 + - Media bus code restricting the enumerated formats, set by the 111 + application. Only applicable to drivers that advertise the 112 + ``V4L2_CAP_IO_MC`` :ref:`capability <device-capabilities>`, shall be 0 113 + otherwise. 114 + * - __u32 115 + - ``reserved``\ [3] 121 116 - Reserved for future extensions. Drivers must set the array to 122 117 zero. 123 118
+11 -2
drivers/media/v4l2-core/v4l2-ioctl.c
··· 264 264 { 265 265 const struct v4l2_fmtdesc *p = arg; 266 266 267 - pr_cont("index=%u, type=%s, flags=0x%x, pixelformat=%c%c%c%c, description='%.*s'\n", 267 + pr_cont("index=%u, type=%s, flags=0x%x, pixelformat=%c%c%c%c, mbus_code=0x%04x, description='%.*s'\n", 268 268 p->index, prt_names(p->type, v4l2_type_names), 269 269 p->flags, (p->pixelformat & 0xff), 270 270 (p->pixelformat >> 8) & 0xff, 271 271 (p->pixelformat >> 16) & 0xff, 272 272 (p->pixelformat >> 24) & 0xff, 273 + p->mbus_code, 273 274 (int)sizeof(p->description), p->description); 274 275 } 275 276 ··· 1473 1472 struct video_device *vdev = video_devdata(file); 1474 1473 struct v4l2_fmtdesc *p = arg; 1475 1474 int ret = check_fmt(file, p->type); 1475 + u32 mbus_code; 1476 1476 u32 cap_mask; 1477 1477 1478 1478 if (ret) 1479 1479 return ret; 1480 1480 ret = -EINVAL; 1481 + 1482 + if (!(vdev->device_caps & V4L2_CAP_IO_MC)) 1483 + p->mbus_code = 0; 1484 + 1485 + mbus_code = p->mbus_code; 1486 + CLEAR_AFTER_FIELD(p, type); 1487 + p->mbus_code = mbus_code; 1481 1488 1482 1489 switch (p->type) { 1483 1490 case V4L2_BUF_TYPE_VIDEO_CAPTURE: ··· 2766 2757 2767 2758 static const struct v4l2_ioctl_info v4l2_ioctls[] = { 2768 2759 IOCTL_INFO(VIDIOC_QUERYCAP, v4l_querycap, v4l_print_querycap, 0), 2769 - IOCTL_INFO(VIDIOC_ENUM_FMT, v4l_enum_fmt, v4l_print_fmtdesc, INFO_FL_CLEAR(v4l2_fmtdesc, type)), 2760 + IOCTL_INFO(VIDIOC_ENUM_FMT, v4l_enum_fmt, v4l_print_fmtdesc, 0), 2770 2761 IOCTL_INFO(VIDIOC_G_FMT, v4l_g_fmt, v4l_print_format, 0), 2771 2762 IOCTL_INFO(VIDIOC_S_FMT, v4l_s_fmt, v4l_print_format, INFO_FL_PRIO), 2772 2763 IOCTL_INFO(VIDIOC_REQBUFS, v4l_reqbufs, v4l_print_requestbuffers, INFO_FL_PRIO | INFO_FL_QUEUE),
+2 -1
include/uapi/linux/videodev2.h
··· 784 784 __u32 flags; 785 785 __u8 description[32]; /* Description string */ 786 786 __u32 pixelformat; /* Format fourcc */ 787 - __u32 reserved[4]; 787 + __u32 mbus_code; /* Media bus code */ 788 + __u32 reserved[3]; 788 789 }; 789 790 790 791 #define V4L2_FMT_FLAG_COMPRESSED 0x0001