diff --git a/Documentation/DocBook/media-entities.tmpl b/Documentation/DocBook/media-entities.tmpl
index dbb9cb2e1ec6..a95eb5783760 100644
--- a/Documentation/DocBook/media-entities.tmpl
+++ b/Documentation/DocBook/media-entities.tmpl
@@ -89,7 +89,9 @@
VIDIOC_SUBDEV_ENUM_FRAME_SIZE">
VIDIOC_SUBDEV_ENUM_MBUS_CODE">
VIDIOC_SUBDEV_G_FMT">
+VIDIOC_SUBDEV_G_FRAME_INTERVAL">
VIDIOC_SUBDEV_S_FMT">
+VIDIOC_SUBDEV_S_FRAME_INTERVAL">
VIDIOC_TRY_ENCODER_CMD">
VIDIOC_TRY_EXT_CTRLS">
VIDIOC_TRY_FMT">
@@ -193,6 +195,8 @@
v4l2_sliced_vbi_cap">
v4l2_sliced_vbi_data">
v4l2_sliced_vbi_format">
+v4l2_subdev_frame_interval">
+v4l2_subdev_frame_interval_enum">
v4l2_subdev_frame_size_enum">
v4l2_subdev_format">
v4l2_subdev_mbus_code_enum">
@@ -331,10 +335,12 @@
+
+
diff --git a/Documentation/DocBook/v4l/v4l2.xml b/Documentation/DocBook/v4l/v4l2.xml
index 2ada2f86bb54..a436716ef3bc 100644
--- a/Documentation/DocBook/v4l/v4l2.xml
+++ b/Documentation/DocBook/v4l/v4l2.xml
@@ -507,9 +507,11 @@ and discussions on the V4L mailing list.
&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;
&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 000000000000..2f8f4f0a0235
--- /dev/null
+++ b/Documentation/DocBook/v4l/vidioc-subdev-enum-frame-interval.xml
@@ -0,0 +1,152 @@
+
+
+ ioctl VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL
+ &manvol;
+
+
+
+ VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL
+ Enumerate frame intervals
+
+
+
+
+
+ int ioctl
+ int fd
+ int request
+ struct v4l2_subdev_frame_interval_enum *
+ argp
+
+
+
+
+
+ Arguments
+
+
+
+ fd
+
+ &fd;
+
+
+
+ request
+
+ VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL
+
+
+
+ argp
+
+
+
+
+
+
+
+
+ Description
+
+
+ Experimental
+ This is an experimental
+ interface and may change in the future.
+
+
+ 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.
+
+ 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.
+
+ To enumerate frame intervals applications initialize the
+ index, pad,
+ code, width and
+ height fields of
+ &v4l2-subdev-frame-interval-enum; and call the
+ VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL 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
+ EINVAL is returned.
+
+ 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.
+
+ 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.
+
+
+ struct v4l2_subdev_frame_interval_enum
+
+ &cs-str;
+
+
+ __u32
+ index
+ Number of the format in the enumeration, set by the
+ application.
+
+
+ __u32
+ pad
+ Pad number as reported by the media controller API.
+
+
+ __u32
+ code
+ The media bus format code, as defined in
+ .
+
+
+ __u32
+ width
+ Frame width, in pixels.
+
+
+ __u32
+ height
+ Frame height, in pixels.
+
+
+ &v4l2-fract;
+ interval
+ Period, in seconds, between consecutive video frames.
+
+
+ __u32
+ reserved[9]
+ Reserved for future extensions. Applications and drivers must
+ set the array to zero.
+
+
+
+
+
+
+
+ &return-value;
+
+
+
+ EINVAL
+
+ The &v4l2-subdev-frame-interval-enum;
+ pad references a non-existing pad, one of
+ the code, width
+ or height fields are invalid for the given
+ pad or the index field is out of bounds.
+
+
+
+
+
+
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 000000000000..0bc3ea22d31f
--- /dev/null
+++ b/Documentation/DocBook/v4l/vidioc-subdev-g-frame-interval.xml
@@ -0,0 +1,141 @@
+
+
+ ioctl VIDIOC_SUBDEV_G_FRAME_INTERVAL, VIDIOC_SUBDEV_S_FRAME_INTERVAL
+ &manvol;
+
+
+
+ VIDIOC_SUBDEV_G_FRAME_INTERVAL
+ VIDIOC_SUBDEV_S_FRAME_INTERVAL
+ Get or set the frame interval on a subdev pad
+
+
+
+
+
+ int ioctl
+ int fd
+ int request
+ struct v4l2_subdev_frame_interval *argp
+
+
+
+
+
+
+ Arguments
+
+
+
+ fd
+
+ &fd;
+
+
+
+ request
+
+ VIDIOC_SUBDEV_G_FRAME_INTERVAL, VIDIOC_SUBDEV_S_FRAME_INTERVAL
+
+
+
+ argp
+
+
+
+
+
+
+
+
+ Description
+
+
+ Experimental
+ This is an experimental
+ interface and may change in the future.
+
+
+ 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.
+
+ To retrieve the current frame interval applications set the
+ pad field of a &v4l2-subdev-frame-interval; to
+ the desired pad number as reported by the media controller API. When they
+ call the VIDIOC_SUBDEV_G_FRAME_INTERVAL ioctl with a
+ pointer to this structure the driver fills the members of the
+ interval field.
+
+ To change the current frame interval applications set both the
+ pad field and all members of the
+ interval field. When they call the
+ VIDIOC_SUBDEV_S_FRAME_INTERVAL 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 VIDIOC_SUBDEV_G_FRAME_INTERVAL call.
+
+
+ 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.
+
+ 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.
+
+
+ struct v4l2_subdev_frame_interval
+
+ &cs-str;
+
+
+ __u32
+ pad
+ Pad number as reported by the media controller API.
+
+
+ &v4l2-fract;
+ interval
+ Period, in seconds, between consecutive video frames.
+
+
+ __u32
+ reserved[9]
+ Reserved for future extensions. Applications and drivers must
+ set the array to zero.
+
+
+
+
+
+
+
+ &return-value;
+
+
+
+ EBUSY
+
+ 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
+ VIDIOC_SUBDEV_S_FRAME_INTERVAL
+
+
+
+ EINVAL
+
+ The &v4l2-subdev-frame-interval; pad
+ references a non-existing pad, or the pad doesn't support frame
+ intervals.
+
+
+
+
+
diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c
index 207cc5cceb29..a4a12563ec3c 100644
--- a/drivers/media/video/v4l2-subdev.c
+++ b/drivers/media/video/v4l2-subdev.c
@@ -232,6 +232,22 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
return v4l2_subdev_call(sd, pad, enum_frame_size, subdev_fh,
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);
+ }
#endif
default:
return -ENOIOCTLCMD;
diff --git a/include/linux/v4l2-subdev.h b/include/linux/v4l2-subdev.h
index 8dbb44873821..c55f9e9e1dd3 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[9];
+};
+
+/**
+ * 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 4215650151be..8b7a78a013c6 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -268,6 +268,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,
@@ -420,6 +424,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,