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@xxxxxxxxxxxxxxxx> Signed-off-by: Sakari Ailus <sakari.ailus@xxxxxxxxxxxxxxxxxxxxxxxxxx> --- Documentation/DocBook/media-entities.tmpl | 6 + Documentation/DocBook/v4l/v4l2.xml | 2 + .../v4l/vidioc-subdev-enum-frame-interval.xml | 146 ++++++++++++++++++++ .../DocBook/v4l/vidioc-subdev-g-frame-interval.xml | 135 ++++++++++++++++++ drivers/media/video/v4l2-subdev.c | 16 ++ include/linux/v4l2-subdev.h | 36 +++++ include/media/v4l2-subdev.h | 7 + 7 files changed, 348 insertions(+), 0 deletions(-) create mode 100644 Documentation/DocBook/v4l/vidioc-subdev-enum-frame-interval.xml create mode 100644 Documentation/DocBook/v4l/vidioc-subdev-g-frame-interval.xml diff --git a/Documentation/DocBook/media-entities.tmpl b/Documentation/DocBook/media-entities.tmpl index 160bca6..71cdc75 100644 --- a/Documentation/DocBook/media-entities.tmpl +++ b/Documentation/DocBook/media-entities.tmpl @@ -89,7 +89,9 @@ <!ENTITY VIDIOC-SUBDEV-ENUM-FRAME-SIZE "<link linkend='vidioc-subdev-enum-frame-size'><constant>VIDIOC_SUBDEV_ENUM_FRAME_SIZE</constant></link>"> <!ENTITY VIDIOC-SUBDEV-ENUM-MBUS-CODE "<link linkend='vidioc-subdev-enum-mbus-code'><constant>VIDIOC_SUBDEV_ENUM_MBUS_CODE</constant></link>"> <!ENTITY VIDIOC-SUBDEV-G-FMT "<link linkend='vidioc-subdev-g-fmt'><constant>VIDIOC_SUBDEV_G_FMT</constant></link>"> +<!ENTITY VIDIOC-SUBDEV-G-FRAME-INTERVAL "<link linkend='vidioc-subdev-g-frame-interval'><constant>VIDIOC_SUBDEV_G_FRAME_INTERVAL</constant></link>"> <!ENTITY VIDIOC-SUBDEV-S-FMT "<link linkend='vidioc-subdev-g-fmt'><constant>VIDIOC_SUBDEV_S_FMT</constant></link>"> +<!ENTITY VIDIOC-SUBDEV-S-FRAME-INTERVAL "<link linkend='vidioc-subdev-g-frame-interval'><constant>VIDIOC_SUBDEV_S_FRAME_INTERVAL</constant></link>"> <!ENTITY VIDIOC-TRY-ENCODER-CMD "<link linkend='vidioc-encoder-cmd'><constant>VIDIOC_TRY_ENCODER_CMD</constant></link>"> <!ENTITY VIDIOC-TRY-EXT-CTRLS "<link linkend='vidioc-g-ext-ctrls'><constant>VIDIOC_TRY_EXT_CTRLS</constant></link>"> <!ENTITY VIDIOC-TRY-FMT "<link linkend='vidioc-g-fmt'><constant>VIDIOC_TRY_FMT</constant></link>"> @@ -190,6 +192,8 @@ <!ENTITY v4l2-sliced-vbi-cap "struct <link linkend='v4l2-sliced-vbi-cap'>v4l2_sliced_vbi_cap</link>"> <!ENTITY v4l2-sliced-vbi-data "struct <link linkend='v4l2-sliced-vbi-data'>v4l2_sliced_vbi_data</link>"> <!ENTITY v4l2-sliced-vbi-format "struct <link linkend='v4l2-sliced-vbi-format'>v4l2_sliced_vbi_format</link>"> +<!ENTITY v4l2-subdev-frame-interval "struct <link linkend='v4l2-subdev-frame-interval'>v4l2_subdev_frame_interval</link>"> +<!ENTITY v4l2-subdev-frame-interval-enum "struct <link linkend='v4l2-subdev-frame-interval-enum'>v4l2_subdev_frame_interval_enum</link>"> <!ENTITY v4l2-subdev-frame-size-enum "struct <link linkend='v4l2-subdev-frame-size-enum'>v4l2_subdev_frame_size_enum</link>"> <!ENTITY v4l2-subdev-format "struct <link linkend='v4l2-subdev-format'>v4l2_subdev_format</link>"> <!ENTITY v4l2-subdev-mbus-code-enum "struct <link linkend='v4l2-subdev-mbus-code-enum'>v4l2_subdev_mbus_code_enum</link>"> @@ -322,10 +326,12 @@ <!ENTITY sub-reqbufs SYSTEM "v4l/vidioc-reqbufs.xml"> <!ENTITY sub-s-hw-freq-seek SYSTEM "v4l/vidioc-s-hw-freq-seek.xml"> <!ENTITY sub-streamon SYSTEM "v4l/vidioc-streamon.xml"> +<!ENTITY sub-subdev-enum-frame-interval SYSTEM "v4l/vidioc-subdev-enum-frame-interval.xml"> <!ENTITY sub-subdev-enum-frame-size SYSTEM "v4l/vidioc-subdev-enum-frame-size.xml"> <!ENTITY sub-subdev-enum-mbus-code SYSTEM "v4l/vidioc-subdev-enum-mbus-code.xml"> <!ENTITY sub-subdev-formats SYSTEM "v4l/subdev-formats.xml"> <!ENTITY sub-subdev-g-fmt SYSTEM "v4l/vidioc-subdev-g-fmt.xml"> +<!ENTITY sub-subdev-g-frame-interval SYSTEM "v4l/vidioc-subdev-g-frame-interval.xml"> <!ENTITY sub-capture-c SYSTEM "v4l/capture.c.xml"> <!ENTITY sub-keytable-c SYSTEM "v4l/keytable.c.xml"> <!ENTITY sub-v4l2grab-c SYSTEM "v4l/v4l2grab.c.xml"> diff --git a/Documentation/DocBook/v4l/v4l2.xml b/Documentation/DocBook/v4l/v4l2.xml index 3a59b82..7806562 100644 --- a/Documentation/DocBook/v4l/v4l2.xml +++ b/Documentation/DocBook/v4l/v4l2.xml @@ -470,9 +470,11 @@ and discussions on the V4L mailing list.</revremark> &sub-reqbufs; &sub-s-hw-freq-seek; &sub-streamon; + &sub-subdev-enum-frame-interval; &sub-subdev-enum-frame-size; &sub-subdev-enum-mbus-code; &sub-subdev-g-fmt; + &sub-subdev-g-frame-interval; &sub-subscribe-event; <!-- End of ioctls. --> &sub-mmap; diff --git a/Documentation/DocBook/v4l/vidioc-subdev-enum-frame-interval.xml b/Documentation/DocBook/v4l/vidioc-subdev-enum-frame-interval.xml new file mode 100644 index 0000000..bcea9d49 --- /dev/null +++ b/Documentation/DocBook/v4l/vidioc-subdev-enum-frame-interval.xml @@ -0,0 +1,146 @@ +<refentry id="vidioc-subdev-enum-frame-interval"> + <refmeta> + <refentrytitle>ioctl VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL</refentrytitle> + &manvol; + </refmeta> + + <refnamediv> + <refname>VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL</refname> + <refpurpose>Enumerate frame intervals</refpurpose> + </refnamediv> + + <refsynopsisdiv> + <funcsynopsis> + <funcprototype> + <funcdef>int <function>ioctl</function></funcdef> + <paramdef>int <parameter>fd</parameter></paramdef> + <paramdef>int <parameter>request</parameter></paramdef> + <paramdef>struct v4l2_subdev_frame_interval_enum * + <parameter>argp</parameter></paramdef> + </funcprototype> + </funcsynopsis> + </refsynopsisdiv> + + <refsect1> + <title>Arguments</title> + + <variablelist> + <varlistentry> + <term><parameter>fd</parameter></term> + <listitem> + <para>&fd;</para> + </listitem> + </varlistentry> + <varlistentry> + <term><parameter>request</parameter></term> + <listitem> + <para>VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL</para> + </listitem> + </varlistentry> + <varlistentry> + <term><parameter>argp</parameter></term> + <listitem> + <para></para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Description</title> + + <para>This ioctl lets applications enumerate available frame intervals on a + given sub-device pad. Frame intervals only makes sense for sub-devices that + can control the frame period on their own. This includes, for instance, + image sensors and TV tuners.</para> + + <para>For the common use case of image sensors, the frame intervals + available on the sub-device output pad depend on the frame format and size + on the same pad. Applications must thus specify the desired format and size + when enumerating frame intervals.</para> + + <para>To enumerate frame intervals applications initialize the + <structfield>index</structfield>, <structfield>pad</structfield>, + <structfield>code</structfield>, <structfield>width</structfield> and + <structfield>height</structfield> fields of + &v4l2-subdev-frame-interval-enum; and call the + <constant>VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL</constant> ioctl with a pointer + to this structure. Drivers fill the rest of the structure or return + an &EINVAL; if one of the input fields is invalid. All frame intervals are + enumerable by beginning at index zero and incrementing by one until + <errorcode>EINVAL</errorcode> is returned.</para> + + <para>Available frame intervals may depend on the current 'try' formats + at other pads of the sub-device, as well as on the current active links. See + &VIDIOC-SUBDEV-G-FMT; for more information about the try formats.</para> + + <para>Sub-devices that support the frame interval enumeration ioctl should + implemented it on a single pad only. Its behaviour when supported on + multiple pads of the same sub-device is not defined.</para> + + <table pgwide="1" frame="none" id="v4l2-subdev-frame-interval-enum"> + <title>struct <structname>v4l2_subdev_frame_interval_enum</structname></title> + <tgroup cols="3"> + &cs-str; + <tbody valign="top"> + <row> + <entry>__u32</entry> + <entry><structfield>index</structfield></entry> + <entry>Number of the format in the enumeration, set by the + application.</entry> + </row> + <row> + <entry>__u32</entry> + <entry><structfield>pad</structfield></entry> + <entry>Pad number as reported by the media controller API.</entry> + </row> + <row> + <entry>__u32</entry> + <entry><structfield>code</structfield></entry> + <entry>The media bus format code, as defined in + <xref linkend="v4l2-mbus-format" />.</entry> + </row> + <row> + <entry>__u32</entry> + <entry><structfield>width</structfield></entry> + <entry>Frame width, in pixels.</entry> + </row> + <row> + <entry>__u32</entry> + <entry><structfield>height</structfield></entry> + <entry>Frame height, in pixels.</entry> + </row> + <row> + <entry>&v4l2-fract;</entry> + <entry><structfield>interval</structfield></entry> + <entry>Period, in seconds, between consecutive video frames.</entry> + </row> + <row> + <entry>__u32</entry> + <entry><structfield>reserved</structfield>[9]</entry> + <entry>Reserved for future extensions. Applications and drivers must + set the array to zero.</entry> + </row> + </tbody> + </tgroup> + </table> + </refsect1> + + <refsect1> + &return-value; + + <variablelist> + <varlistentry> + <term><errorcode>EINVAL</errorcode></term> + <listitem> + <para>The &v4l2-subdev-frame-interval-enum; + <structfield>pad</structfield> references a non-existing pad, one of + the <structfield>code</structfield>, <structfield>width</structfield> + or <structfield>height</structfield> fields are invalid for the given + pad or the <structfield>index</structfield> field is out of bounds. + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> +</refentry> diff --git a/Documentation/DocBook/v4l/vidioc-subdev-g-frame-interval.xml b/Documentation/DocBook/v4l/vidioc-subdev-g-frame-interval.xml new file mode 100644 index 0000000..1d0e0e1 --- /dev/null +++ b/Documentation/DocBook/v4l/vidioc-subdev-g-frame-interval.xml @@ -0,0 +1,135 @@ +<refentry id="vidioc-subdev-g-frame-interval"> + <refmeta> + <refentrytitle>ioctl VIDIOC_SUBDEV_G_FRAME_INTERVAL, VIDIOC_SUBDEV_S_FRAME_INTERVAL</refentrytitle> + &manvol; + </refmeta> + + <refnamediv> + <refname>VIDIOC_SUBDEV_G_FRAME_INTERVAL</refname> + <refname>VIDIOC_SUBDEV_S_FRAME_INTERVAL</refname> + <refpurpose>Get or set the frame interval on a subdev pad</refpurpose> + </refnamediv> + + <refsynopsisdiv> + <funcsynopsis> + <funcprototype> + <funcdef>int <function>ioctl</function></funcdef> + <paramdef>int <parameter>fd</parameter></paramdef> + <paramdef>int <parameter>request</parameter></paramdef> + <paramdef>struct v4l2_subdev_frame_interval *<parameter>argp</parameter> + </paramdef> + </funcprototype> + </funcsynopsis> + </refsynopsisdiv> + + <refsect1> + <title>Arguments</title> + + <variablelist> + <varlistentry> + <term><parameter>fd</parameter></term> + <listitem> + <para>&fd;</para> + </listitem> + </varlistentry> + <varlistentry> + <term><parameter>request</parameter></term> + <listitem> + <para>VIDIOC_SUBDEV_G_FRAME_INTERVAL, VIDIOC_SUBDEV_S_FRAME_INTERVAL</para> + </listitem> + </varlistentry> + <varlistentry> + <term><parameter>argp</parameter></term> + <listitem> + <para></para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Description</title> + + <para>These ioctls are used to get and set the frame interval at specific + subdev pads in the image pipeline. The frame interval only makes sense for + sub-devices that can control the frame period on their own. This includes, + for instance, image sensors and TV tuners. Sub-devices that don't support + frame intervals must not implement these ioctls.</para> + + <para>To retrieve the current frame interval applications set the + <structfield>pad</structfield> field of a &v4l2-subdev-frame-interval; to + the desired pad number as reported by the media controller API. When they + call the <constant>VIDIOC_SUBDEV_G_FRAME_INTERVAL</constant> ioctl with a + pointer to this structure the driver fills the members of the + <structfield>interval</structfield> field.</para> + + <para>To change the current frame interval applications set both the + <structfield>pad</structfield> field and all members of the + <structfield>interval</structfield> field. When they call the + <constant>VIDIOC_SUBDEV_S_FRAME_INTERVAL</constant> ioctl with a pointer to + this structure the driver verifies the requested interval, adjusts it based + on the hardware capabilities and configures the device. Upon return the + &v4l2-subdev-frame-interval; contains the current frame interval as would be + returned by a <constant>VIDIOC_SUBDEV_G_FRAME_INTERVAL</constant> call. + </para> + + <para>Drivers must not return an error solely because the requested interval + doesn't match the device capabilities. They must instead modify the interval + to match what the hardware can provide. The modified interval should be as + close as possible to the original request.</para> + + <para>Sub-devices that support the frame interval ioctls should implement + them on a single pad only. Their behaviour when supported on multiple pads + of the same sub-device is not defined.</para> + + <table pgwide="1" frame="none" id="v4l2-subdev-frame-interval"> + <title>struct <structname>v4l2_subdev_frame_interval</structname></title> + <tgroup cols="3"> + &cs-str; + <tbody valign="top"> + <row> + <entry>__u32</entry> + <entry><structfield>pad</structfield></entry> + <entry>Pad number as reported by the media controller API.</entry> + </row> + <row> + <entry>&v4l2-fract;</entry> + <entry><structfield>interval</structfield></entry> + <entry>Period, in seconds, between consecutive video frames.</entry> + </row> + <row> + <entry>__u32</entry> + <entry><structfield>reserved</structfield>[5]</entry> + <entry>Reserved for future extensions. Applications and drivers must + set the array to zero.</entry> + </row> + </tbody> + </tgroup> + </table> + </refsect1> + + <refsect1> + &return-value; + + <variablelist> + <varlistentry> + <term><errorcode>EBUSY</errorcode></term> + <listitem> + <para>The frame interval can't be changed because the pad is currently + busy. This can be caused, for instance, by an active video stream on + the pad. The ioctl must not be retried without performing another + action to fix the problem first. Only returned by + <constant>VIDIOC_SUBDEV_S_FRAME_INTERVAL</constant></para> + </listitem> + </varlistentry> + <varlistentry> + <term><errorcode>EINVAL</errorcode></term> + <listitem> + <para>The &v4l2-subdev-frame-interval; <structfield>pad</structfield> + references a non-existing pad, or the pad doesn't support frame + intervals.</para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> +</refentry> diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c index 26dafb7..7c3c079 100644 --- a/drivers/media/video/v4l2-subdev.c +++ b/drivers/media/video/v4l2-subdev.c @@ -215,6 +215,22 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) fse); } + case VIDIOC_SUBDEV_G_FRAME_INTERVAL: + return v4l2_subdev_call(sd, video, g_frame_interval, arg); + + case VIDIOC_SUBDEV_S_FRAME_INTERVAL: + return v4l2_subdev_call(sd, video, s_frame_interval, arg); + + case VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL: { + struct v4l2_subdev_frame_interval_enum *fie = arg; + + if (fie->pad >= sd->entity.num_pads) + return -EINVAL; + + return v4l2_subdev_call(sd, pad, enum_frame_interval, subdev_fh, + fie); + } + default: return -ENOIOCTLCMD; } diff --git a/include/linux/v4l2-subdev.h b/include/linux/v4l2-subdev.h index 039c6e4..7af0c34 100644 --- a/include/linux/v4l2-subdev.h +++ b/include/linux/v4l2-subdev.h @@ -80,11 +80,47 @@ struct v4l2_subdev_frame_size_enum { __u32 reserved[9]; }; +/** + * struct v4l2_subdev_frame_interval - Pad-level frame rate + * @pad: pad number, as reported by the media API + * @interval: frame interval in seconds + */ +struct v4l2_subdev_frame_interval { + __u32 pad; + struct v4l2_fract interval; + __u32 reserved[5]; +}; + +/** + * struct v4l2_subdev_frame_interval_enum - Frame interval enumeration + * @pad: pad number, as reported by the media API + * @index: frame interval index during enumeration + * @code: format code (from enum v4l2_mbus_pixelcode) + * @width: frame width in pixels + * @height: frame height in pixels + * @interval: frame interval in seconds + */ +struct v4l2_subdev_frame_interval_enum { + __u32 index; + __u32 pad; + __u32 code; + __u32 width; + __u32 height; + struct v4l2_fract interval; + __u32 reserved[9]; +}; + #define VIDIOC_SUBDEV_G_FMT _IOWR('V', 4, struct v4l2_subdev_format) #define VIDIOC_SUBDEV_S_FMT _IOWR('V', 5, struct v4l2_subdev_format) +#define VIDIOC_SUBDEV_G_FRAME_INTERVAL \ + _IOWR('V', 21, struct v4l2_subdev_frame_interval) +#define VIDIOC_SUBDEV_S_FRAME_INTERVAL \ + _IOWR('V', 22, struct v4l2_subdev_frame_interval) #define VIDIOC_SUBDEV_ENUM_MBUS_CODE \ _IOWR('V', 2, struct v4l2_subdev_mbus_code_enum) #define VIDIOC_SUBDEV_ENUM_FRAME_SIZE \ _IOWR('V', 74, struct v4l2_subdev_frame_size_enum) +#define VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL \ + _IOWR('V', 75, struct v4l2_subdev_frame_interval_enum) #endif diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 640e838..65f5482 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -276,6 +276,10 @@ struct v4l2_subdev_video_ops { int (*s_crop)(struct v4l2_subdev *sd, struct v4l2_crop *crop); int (*g_parm)(struct v4l2_subdev *sd, struct v4l2_streamparm *param); int (*s_parm)(struct v4l2_subdev *sd, struct v4l2_streamparm *param); + int (*g_frame_interval)(struct v4l2_subdev *sd, + struct v4l2_subdev_frame_interval *interval); + int (*s_frame_interval)(struct v4l2_subdev *sd, + struct v4l2_subdev_frame_interval *interval); int (*enum_framesizes)(struct v4l2_subdev *sd, struct v4l2_frmsizeenum *fsize); int (*enum_frameintervals)(struct v4l2_subdev *sd, struct v4l2_frmivalenum *fival); int (*enum_dv_presets) (struct v4l2_subdev *sd, @@ -426,6 +430,9 @@ struct v4l2_subdev_pad_ops { int (*enum_frame_size)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, struct v4l2_subdev_frame_size_enum *fse); + int (*enum_frame_interval)(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_frame_interval_enum *fie); int (*get_fmt)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, struct v4l2_subdev_format *format); int (*set_fmt)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, -- 1.7.2.2 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html