Commit 35c3017a29d278c4405a7f3ab30b814999d156d3

Authored by Laurent Pinchart
Committed by Mauro Carvalho Chehab
1 parent 333c8b9778

[media] v4l: v4l2_subdev userspace frame interval API

The three new ioctl VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL,
VIDIOC_SUBDEV_G_FRAME_INTERVAL and VIDIOC_SUBDEV_S_FRAME_INTERVAL can be
used to enumerate and configure a subdev's frame rate from userspace.

Two new video::g/s_frame_interval subdev operations are introduced to
support those ioctls. The existing video::g/s_parm operations are
deprecated and shouldn't be used anymore.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Sakari Ailus <sakari.ailus@iki.fi>
Acked-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

Showing 7 changed files with 360 additions and 0 deletions Side-by-side Diff

Documentation/DocBook/media-entities.tmpl
... ... @@ -89,7 +89,9 @@
89 89 <!ENTITY VIDIOC-SUBDEV-ENUM-FRAME-SIZE "<link linkend='vidioc-subdev-enum-frame-size'><constant>VIDIOC_SUBDEV_ENUM_FRAME_SIZE</constant></link>">
90 90 <!ENTITY VIDIOC-SUBDEV-ENUM-MBUS-CODE "<link linkend='vidioc-subdev-enum-mbus-code'><constant>VIDIOC_SUBDEV_ENUM_MBUS_CODE</constant></link>">
91 91 <!ENTITY VIDIOC-SUBDEV-G-FMT "<link linkend='vidioc-subdev-g-fmt'><constant>VIDIOC_SUBDEV_G_FMT</constant></link>">
  92 +<!ENTITY VIDIOC-SUBDEV-G-FRAME-INTERVAL "<link linkend='vidioc-subdev-g-frame-interval'><constant>VIDIOC_SUBDEV_G_FRAME_INTERVAL</constant></link>">
92 93 <!ENTITY VIDIOC-SUBDEV-S-FMT "<link linkend='vidioc-subdev-g-fmt'><constant>VIDIOC_SUBDEV_S_FMT</constant></link>">
  94 +<!ENTITY VIDIOC-SUBDEV-S-FRAME-INTERVAL "<link linkend='vidioc-subdev-g-frame-interval'><constant>VIDIOC_SUBDEV_S_FRAME_INTERVAL</constant></link>">
93 95 <!ENTITY VIDIOC-TRY-ENCODER-CMD "<link linkend='vidioc-encoder-cmd'><constant>VIDIOC_TRY_ENCODER_CMD</constant></link>">
94 96 <!ENTITY VIDIOC-TRY-EXT-CTRLS "<link linkend='vidioc-g-ext-ctrls'><constant>VIDIOC_TRY_EXT_CTRLS</constant></link>">
95 97 <!ENTITY VIDIOC-TRY-FMT "<link linkend='vidioc-g-fmt'><constant>VIDIOC_TRY_FMT</constant></link>">
... ... @@ -193,6 +195,8 @@
193 195 <!ENTITY v4l2-sliced-vbi-cap "struct&nbsp;<link linkend='v4l2-sliced-vbi-cap'>v4l2_sliced_vbi_cap</link>">
194 196 <!ENTITY v4l2-sliced-vbi-data "struct&nbsp;<link linkend='v4l2-sliced-vbi-data'>v4l2_sliced_vbi_data</link>">
195 197 <!ENTITY v4l2-sliced-vbi-format "struct&nbsp;<link linkend='v4l2-sliced-vbi-format'>v4l2_sliced_vbi_format</link>">
  198 +<!ENTITY v4l2-subdev-frame-interval "struct&nbsp;<link linkend='v4l2-subdev-frame-interval'>v4l2_subdev_frame_interval</link>">
  199 +<!ENTITY v4l2-subdev-frame-interval-enum "struct&nbsp;<link linkend='v4l2-subdev-frame-interval-enum'>v4l2_subdev_frame_interval_enum</link>">
196 200 <!ENTITY v4l2-subdev-frame-size-enum "struct&nbsp;<link linkend='v4l2-subdev-frame-size-enum'>v4l2_subdev_frame_size_enum</link>">
197 201 <!ENTITY v4l2-subdev-format "struct&nbsp;<link linkend='v4l2-subdev-format'>v4l2_subdev_format</link>">
198 202 <!ENTITY v4l2-subdev-mbus-code-enum "struct&nbsp;<link linkend='v4l2-subdev-mbus-code-enum'>v4l2_subdev_mbus_code_enum</link>">
199 203  
... ... @@ -331,10 +335,12 @@
331 335 <!ENTITY sub-reqbufs SYSTEM "v4l/vidioc-reqbufs.xml">
332 336 <!ENTITY sub-s-hw-freq-seek SYSTEM "v4l/vidioc-s-hw-freq-seek.xml">
333 337 <!ENTITY sub-streamon SYSTEM "v4l/vidioc-streamon.xml">
  338 +<!ENTITY sub-subdev-enum-frame-interval SYSTEM "v4l/vidioc-subdev-enum-frame-interval.xml">
334 339 <!ENTITY sub-subdev-enum-frame-size SYSTEM "v4l/vidioc-subdev-enum-frame-size.xml">
335 340 <!ENTITY sub-subdev-enum-mbus-code SYSTEM "v4l/vidioc-subdev-enum-mbus-code.xml">
336 341 <!ENTITY sub-subdev-formats SYSTEM "v4l/subdev-formats.xml">
337 342 <!ENTITY sub-subdev-g-fmt SYSTEM "v4l/vidioc-subdev-g-fmt.xml">
  343 +<!ENTITY sub-subdev-g-frame-interval SYSTEM "v4l/vidioc-subdev-g-frame-interval.xml">
338 344 <!ENTITY sub-capture-c SYSTEM "v4l/capture.c.xml">
339 345 <!ENTITY sub-keytable-c SYSTEM "v4l/keytable.c.xml">
340 346 <!ENTITY sub-v4l2grab-c SYSTEM "v4l/v4l2grab.c.xml">
Documentation/DocBook/v4l/v4l2.xml
... ... @@ -507,9 +507,11 @@
507 507 &sub-reqbufs;
508 508 &sub-s-hw-freq-seek;
509 509 &sub-streamon;
  510 + &sub-subdev-enum-frame-interval;
510 511 &sub-subdev-enum-frame-size;
511 512 &sub-subdev-enum-mbus-code;
512 513 &sub-subdev-g-fmt;
  514 + &sub-subdev-g-frame-interval;
513 515 &sub-subscribe-event;
514 516 <!-- End of ioctls. -->
515 517 &sub-mmap;
Documentation/DocBook/v4l/vidioc-subdev-enum-frame-interval.xml
  1 +<refentry id="vidioc-subdev-enum-frame-interval">
  2 + <refmeta>
  3 + <refentrytitle>ioctl VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL</refentrytitle>
  4 + &manvol;
  5 + </refmeta>
  6 +
  7 + <refnamediv>
  8 + <refname>VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL</refname>
  9 + <refpurpose>Enumerate frame intervals</refpurpose>
  10 + </refnamediv>
  11 +
  12 + <refsynopsisdiv>
  13 + <funcsynopsis>
  14 + <funcprototype>
  15 + <funcdef>int <function>ioctl</function></funcdef>
  16 + <paramdef>int <parameter>fd</parameter></paramdef>
  17 + <paramdef>int <parameter>request</parameter></paramdef>
  18 + <paramdef>struct v4l2_subdev_frame_interval_enum *
  19 + <parameter>argp</parameter></paramdef>
  20 + </funcprototype>
  21 + </funcsynopsis>
  22 + </refsynopsisdiv>
  23 +
  24 + <refsect1>
  25 + <title>Arguments</title>
  26 +
  27 + <variablelist>
  28 + <varlistentry>
  29 + <term><parameter>fd</parameter></term>
  30 + <listitem>
  31 + <para>&fd;</para>
  32 + </listitem>
  33 + </varlistentry>
  34 + <varlistentry>
  35 + <term><parameter>request</parameter></term>
  36 + <listitem>
  37 + <para>VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL</para>
  38 + </listitem>
  39 + </varlistentry>
  40 + <varlistentry>
  41 + <term><parameter>argp</parameter></term>
  42 + <listitem>
  43 + <para></para>
  44 + </listitem>
  45 + </varlistentry>
  46 + </variablelist>
  47 + </refsect1>
  48 +
  49 + <refsect1>
  50 + <title>Description</title>
  51 +
  52 + <note>
  53 + <title>Experimental</title>
  54 + <para>This is an <link linkend="experimental">experimental</link>
  55 + interface and may change in the future.</para>
  56 + </note>
  57 +
  58 + <para>This ioctl lets applications enumerate available frame intervals on a
  59 + given sub-device pad. Frame intervals only makes sense for sub-devices that
  60 + can control the frame period on their own. This includes, for instance,
  61 + image sensors and TV tuners.</para>
  62 +
  63 + <para>For the common use case of image sensors, the frame intervals
  64 + available on the sub-device output pad depend on the frame format and size
  65 + on the same pad. Applications must thus specify the desired format and size
  66 + when enumerating frame intervals.</para>
  67 +
  68 + <para>To enumerate frame intervals applications initialize the
  69 + <structfield>index</structfield>, <structfield>pad</structfield>,
  70 + <structfield>code</structfield>, <structfield>width</structfield> and
  71 + <structfield>height</structfield> fields of
  72 + &v4l2-subdev-frame-interval-enum; and call the
  73 + <constant>VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL</constant> ioctl with a pointer
  74 + to this structure. Drivers fill the rest of the structure or return
  75 + an &EINVAL; if one of the input fields is invalid. All frame intervals are
  76 + enumerable by beginning at index zero and incrementing by one until
  77 + <errorcode>EINVAL</errorcode> is returned.</para>
  78 +
  79 + <para>Available frame intervals may depend on the current 'try' formats
  80 + at other pads of the sub-device, as well as on the current active links. See
  81 + &VIDIOC-SUBDEV-G-FMT; for more information about the try formats.</para>
  82 +
  83 + <para>Sub-devices that support the frame interval enumeration ioctl should
  84 + implemented it on a single pad only. Its behaviour when supported on
  85 + multiple pads of the same sub-device is not defined.</para>
  86 +
  87 + <table pgwide="1" frame="none" id="v4l2-subdev-frame-interval-enum">
  88 + <title>struct <structname>v4l2_subdev_frame_interval_enum</structname></title>
  89 + <tgroup cols="3">
  90 + &cs-str;
  91 + <tbody valign="top">
  92 + <row>
  93 + <entry>__u32</entry>
  94 + <entry><structfield>index</structfield></entry>
  95 + <entry>Number of the format in the enumeration, set by the
  96 + application.</entry>
  97 + </row>
  98 + <row>
  99 + <entry>__u32</entry>
  100 + <entry><structfield>pad</structfield></entry>
  101 + <entry>Pad number as reported by the media controller API.</entry>
  102 + </row>
  103 + <row>
  104 + <entry>__u32</entry>
  105 + <entry><structfield>code</structfield></entry>
  106 + <entry>The media bus format code, as defined in
  107 + <xref linkend="v4l2-mbus-format" />.</entry>
  108 + </row>
  109 + <row>
  110 + <entry>__u32</entry>
  111 + <entry><structfield>width</structfield></entry>
  112 + <entry>Frame width, in pixels.</entry>
  113 + </row>
  114 + <row>
  115 + <entry>__u32</entry>
  116 + <entry><structfield>height</structfield></entry>
  117 + <entry>Frame height, in pixels.</entry>
  118 + </row>
  119 + <row>
  120 + <entry>&v4l2-fract;</entry>
  121 + <entry><structfield>interval</structfield></entry>
  122 + <entry>Period, in seconds, between consecutive video frames.</entry>
  123 + </row>
  124 + <row>
  125 + <entry>__u32</entry>
  126 + <entry><structfield>reserved</structfield>[9]</entry>
  127 + <entry>Reserved for future extensions. Applications and drivers must
  128 + set the array to zero.</entry>
  129 + </row>
  130 + </tbody>
  131 + </tgroup>
  132 + </table>
  133 + </refsect1>
  134 +
  135 + <refsect1>
  136 + &return-value;
  137 +
  138 + <variablelist>
  139 + <varlistentry>
  140 + <term><errorcode>EINVAL</errorcode></term>
  141 + <listitem>
  142 + <para>The &v4l2-subdev-frame-interval-enum;
  143 + <structfield>pad</structfield> references a non-existing pad, one of
  144 + the <structfield>code</structfield>, <structfield>width</structfield>
  145 + or <structfield>height</structfield> fields are invalid for the given
  146 + pad or the <structfield>index</structfield> field is out of bounds.
  147 + </para>
  148 + </listitem>
  149 + </varlistentry>
  150 + </variablelist>
  151 + </refsect1>
  152 +</refentry>
Documentation/DocBook/v4l/vidioc-subdev-g-frame-interval.xml
  1 +<refentry id="vidioc-subdev-g-frame-interval">
  2 + <refmeta>
  3 + <refentrytitle>ioctl VIDIOC_SUBDEV_G_FRAME_INTERVAL, VIDIOC_SUBDEV_S_FRAME_INTERVAL</refentrytitle>
  4 + &manvol;
  5 + </refmeta>
  6 +
  7 + <refnamediv>
  8 + <refname>VIDIOC_SUBDEV_G_FRAME_INTERVAL</refname>
  9 + <refname>VIDIOC_SUBDEV_S_FRAME_INTERVAL</refname>
  10 + <refpurpose>Get or set the frame interval on a subdev pad</refpurpose>
  11 + </refnamediv>
  12 +
  13 + <refsynopsisdiv>
  14 + <funcsynopsis>
  15 + <funcprototype>
  16 + <funcdef>int <function>ioctl</function></funcdef>
  17 + <paramdef>int <parameter>fd</parameter></paramdef>
  18 + <paramdef>int <parameter>request</parameter></paramdef>
  19 + <paramdef>struct v4l2_subdev_frame_interval *<parameter>argp</parameter>
  20 + </paramdef>
  21 + </funcprototype>
  22 + </funcsynopsis>
  23 + </refsynopsisdiv>
  24 +
  25 + <refsect1>
  26 + <title>Arguments</title>
  27 +
  28 + <variablelist>
  29 + <varlistentry>
  30 + <term><parameter>fd</parameter></term>
  31 + <listitem>
  32 + <para>&fd;</para>
  33 + </listitem>
  34 + </varlistentry>
  35 + <varlistentry>
  36 + <term><parameter>request</parameter></term>
  37 + <listitem>
  38 + <para>VIDIOC_SUBDEV_G_FRAME_INTERVAL, VIDIOC_SUBDEV_S_FRAME_INTERVAL</para>
  39 + </listitem>
  40 + </varlistentry>
  41 + <varlistentry>
  42 + <term><parameter>argp</parameter></term>
  43 + <listitem>
  44 + <para></para>
  45 + </listitem>
  46 + </varlistentry>
  47 + </variablelist>
  48 + </refsect1>
  49 +
  50 + <refsect1>
  51 + <title>Description</title>
  52 +
  53 + <note>
  54 + <title>Experimental</title>
  55 + <para>This is an <link linkend="experimental">experimental</link>
  56 + interface and may change in the future.</para>
  57 + </note>
  58 +
  59 + <para>These ioctls are used to get and set the frame interval at specific
  60 + subdev pads in the image pipeline. The frame interval only makes sense for
  61 + sub-devices that can control the frame period on their own. This includes,
  62 + for instance, image sensors and TV tuners. Sub-devices that don't support
  63 + frame intervals must not implement these ioctls.</para>
  64 +
  65 + <para>To retrieve the current frame interval applications set the
  66 + <structfield>pad</structfield> field of a &v4l2-subdev-frame-interval; to
  67 + the desired pad number as reported by the media controller API. When they
  68 + call the <constant>VIDIOC_SUBDEV_G_FRAME_INTERVAL</constant> ioctl with a
  69 + pointer to this structure the driver fills the members of the
  70 + <structfield>interval</structfield> field.</para>
  71 +
  72 + <para>To change the current frame interval applications set both the
  73 + <structfield>pad</structfield> field and all members of the
  74 + <structfield>interval</structfield> field. When they call the
  75 + <constant>VIDIOC_SUBDEV_S_FRAME_INTERVAL</constant> ioctl with a pointer to
  76 + this structure the driver verifies the requested interval, adjusts it based
  77 + on the hardware capabilities and configures the device. Upon return the
  78 + &v4l2-subdev-frame-interval; contains the current frame interval as would be
  79 + returned by a <constant>VIDIOC_SUBDEV_G_FRAME_INTERVAL</constant> call.
  80 + </para>
  81 +
  82 + <para>Drivers must not return an error solely because the requested interval
  83 + doesn't match the device capabilities. They must instead modify the interval
  84 + to match what the hardware can provide. The modified interval should be as
  85 + close as possible to the original request.</para>
  86 +
  87 + <para>Sub-devices that support the frame interval ioctls should implement
  88 + them on a single pad only. Their behaviour when supported on multiple pads
  89 + of the same sub-device is not defined.</para>
  90 +
  91 + <table pgwide="1" frame="none" id="v4l2-subdev-frame-interval">
  92 + <title>struct <structname>v4l2_subdev_frame_interval</structname></title>
  93 + <tgroup cols="3">
  94 + &cs-str;
  95 + <tbody valign="top">
  96 + <row>
  97 + <entry>__u32</entry>
  98 + <entry><structfield>pad</structfield></entry>
  99 + <entry>Pad number as reported by the media controller API.</entry>
  100 + </row>
  101 + <row>
  102 + <entry>&v4l2-fract;</entry>
  103 + <entry><structfield>interval</structfield></entry>
  104 + <entry>Period, in seconds, between consecutive video frames.</entry>
  105 + </row>
  106 + <row>
  107 + <entry>__u32</entry>
  108 + <entry><structfield>reserved</structfield>[9]</entry>
  109 + <entry>Reserved for future extensions. Applications and drivers must
  110 + set the array to zero.</entry>
  111 + </row>
  112 + </tbody>
  113 + </tgroup>
  114 + </table>
  115 + </refsect1>
  116 +
  117 + <refsect1>
  118 + &return-value;
  119 +
  120 + <variablelist>
  121 + <varlistentry>
  122 + <term><errorcode>EBUSY</errorcode></term>
  123 + <listitem>
  124 + <para>The frame interval can't be changed because the pad is currently
  125 + busy. This can be caused, for instance, by an active video stream on
  126 + the pad. The ioctl must not be retried without performing another
  127 + action to fix the problem first. Only returned by
  128 + <constant>VIDIOC_SUBDEV_S_FRAME_INTERVAL</constant></para>
  129 + </listitem>
  130 + </varlistentry>
  131 + <varlistentry>
  132 + <term><errorcode>EINVAL</errorcode></term>
  133 + <listitem>
  134 + <para>The &v4l2-subdev-frame-interval; <structfield>pad</structfield>
  135 + references a non-existing pad, or the pad doesn't support frame
  136 + intervals.</para>
  137 + </listitem>
  138 + </varlistentry>
  139 + </variablelist>
  140 + </refsect1>
  141 +</refentry>
drivers/media/video/v4l2-subdev.c
... ... @@ -232,6 +232,22 @@
232 232 return v4l2_subdev_call(sd, pad, enum_frame_size, subdev_fh,
233 233 fse);
234 234 }
  235 +
  236 + case VIDIOC_SUBDEV_G_FRAME_INTERVAL:
  237 + return v4l2_subdev_call(sd, video, g_frame_interval, arg);
  238 +
  239 + case VIDIOC_SUBDEV_S_FRAME_INTERVAL:
  240 + return v4l2_subdev_call(sd, video, s_frame_interval, arg);
  241 +
  242 + case VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL: {
  243 + struct v4l2_subdev_frame_interval_enum *fie = arg;
  244 +
  245 + if (fie->pad >= sd->entity.num_pads)
  246 + return -EINVAL;
  247 +
  248 + return v4l2_subdev_call(sd, pad, enum_frame_interval, subdev_fh,
  249 + fie);
  250 + }
235 251 #endif
236 252 default:
237 253 return -ENOIOCTLCMD;
include/linux/v4l2-subdev.h
... ... @@ -80,12 +80,48 @@
80 80 __u32 reserved[9];
81 81 };
82 82  
  83 +/**
  84 + * struct v4l2_subdev_frame_interval - Pad-level frame rate
  85 + * @pad: pad number, as reported by the media API
  86 + * @interval: frame interval in seconds
  87 + */
  88 +struct v4l2_subdev_frame_interval {
  89 + __u32 pad;
  90 + struct v4l2_fract interval;
  91 + __u32 reserved[9];
  92 +};
  93 +
  94 +/**
  95 + * struct v4l2_subdev_frame_interval_enum - Frame interval enumeration
  96 + * @pad: pad number, as reported by the media API
  97 + * @index: frame interval index during enumeration
  98 + * @code: format code (from enum v4l2_mbus_pixelcode)
  99 + * @width: frame width in pixels
  100 + * @height: frame height in pixels
  101 + * @interval: frame interval in seconds
  102 + */
  103 +struct v4l2_subdev_frame_interval_enum {
  104 + __u32 index;
  105 + __u32 pad;
  106 + __u32 code;
  107 + __u32 width;
  108 + __u32 height;
  109 + struct v4l2_fract interval;
  110 + __u32 reserved[9];
  111 +};
  112 +
83 113 #define VIDIOC_SUBDEV_G_FMT _IOWR('V', 4, struct v4l2_subdev_format)
84 114 #define VIDIOC_SUBDEV_S_FMT _IOWR('V', 5, struct v4l2_subdev_format)
  115 +#define VIDIOC_SUBDEV_G_FRAME_INTERVAL \
  116 + _IOWR('V', 21, struct v4l2_subdev_frame_interval)
  117 +#define VIDIOC_SUBDEV_S_FRAME_INTERVAL \
  118 + _IOWR('V', 22, struct v4l2_subdev_frame_interval)
85 119 #define VIDIOC_SUBDEV_ENUM_MBUS_CODE \
86 120 _IOWR('V', 2, struct v4l2_subdev_mbus_code_enum)
87 121 #define VIDIOC_SUBDEV_ENUM_FRAME_SIZE \
88 122 _IOWR('V', 74, struct v4l2_subdev_frame_size_enum)
  123 +#define VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL \
  124 + _IOWR('V', 75, struct v4l2_subdev_frame_interval_enum)
89 125  
90 126 #endif
include/media/v4l2-subdev.h
... ... @@ -268,6 +268,10 @@
268 268 int (*s_crop)(struct v4l2_subdev *sd, struct v4l2_crop *crop);
269 269 int (*g_parm)(struct v4l2_subdev *sd, struct v4l2_streamparm *param);
270 270 int (*s_parm)(struct v4l2_subdev *sd, struct v4l2_streamparm *param);
  271 + int (*g_frame_interval)(struct v4l2_subdev *sd,
  272 + struct v4l2_subdev_frame_interval *interval);
  273 + int (*s_frame_interval)(struct v4l2_subdev *sd,
  274 + struct v4l2_subdev_frame_interval *interval);
271 275 int (*enum_framesizes)(struct v4l2_subdev *sd, struct v4l2_frmsizeenum *fsize);
272 276 int (*enum_frameintervals)(struct v4l2_subdev *sd, struct v4l2_frmivalenum *fival);
273 277 int (*enum_dv_presets) (struct v4l2_subdev *sd,
... ... @@ -420,6 +424,9 @@
420 424 int (*enum_frame_size)(struct v4l2_subdev *sd,
421 425 struct v4l2_subdev_fh *fh,
422 426 struct v4l2_subdev_frame_size_enum *fse);
  427 + int (*enum_frame_interval)(struct v4l2_subdev *sd,
  428 + struct v4l2_subdev_fh *fh,
  429 + struct v4l2_subdev_frame_interval_enum *fie);
423 430 int (*get_fmt)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
424 431 struct v4l2_subdev_format *format);
425 432 int (*set_fmt)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,