Commit 805d4311 authored by Laurent Pinchart's avatar Laurent Pinchart Committed by Hans Verkuil
Browse files

media: v4l2-subdev: Add which field to struct v4l2_subdev_frame_interval



Due to a historical mishap, the v4l2_subdev_frame_interval structure
is the only part of the V4L2 subdev userspace API that doesn't contain a
'which' field. This prevents trying frame intervals using the subdev
'TRY' state mechanism.

Adding a 'which' field is simple as the structure has 8 reserved fields.
This would however break userspace as the field is currently set to 0,
corresponding to V4L2_SUBDEV_FORMAT_TRY, while the corresponding ioctls
currently operate on the 'ACTIVE' state. We thus need to add a new
subdev client cap, V4L2_SUBDEV_CLIENT_CAP_INTERVAL_USES_WHICH, to
indicate that userspace is aware of this new field.

All drivers that implement the subdev .get_frame_interval() and
.set_frame_interval() operations are updated to return -EINVAL when
operating on the TRY state, preserving the current behaviour.

While at it, fix a bad copy&paste in the documentation of the struct
v4l2_subdev_frame_interval_enum 'which' field.

Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de> # for imx-media
Reviewed-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Reviewed-by: Luca Ceresoli <luca.ceresoli@bootlin.com> # for tegra-video
Reviewed-by: default avatarMauro Carvalho Chehab <mchehab@kernel.org>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
parent 287fe160
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -71,6 +71,11 @@ is unknown to the kernel.
        of 'stream' fields (referring to the stream number) with various
        ioctls. If this is not set (which is the default), the 'stream' fields
        will be forced to 0 by the kernel.
    * - ``V4L2_SUBDEV_CLIENT_CAP_INTERVAL_USES_WHICH``
      - The client is aware of the :c:type:`v4l2_subdev_frame_interval`
        ``which`` field. If this is not set (which is the default), the
        ``which`` field is forced to ``V4L2_SUBDEV_FORMAT_ACTIVE`` by the
        kernel.

Return Value
============
+11 −6
Original line number Diff line number Diff line
@@ -58,8 +58,9 @@ struct
contains the current frame interval as would be returned by a
``VIDIOC_SUBDEV_G_FRAME_INTERVAL`` call.

Calling ``VIDIOC_SUBDEV_S_FRAME_INTERVAL`` on a subdev device node that has been
registered in read-only mode is not allowed. An error is returned and the errno
If the subdev device node has been registered in read-only mode, calls to
``VIDIOC_SUBDEV_S_FRAME_INTERVAL`` are only valid if the ``which`` field is set
to ``V4L2_SUBDEV_FORMAT_TRY``, otherwise an error is returned and the errno
variable is set to ``-EPERM``.

Drivers must not return an error solely because the requested interval
@@ -93,7 +94,11 @@ the same sub-device is not defined.
      - ``stream``
      - Stream identifier.
    * - __u32
      - ``reserved``\ [8]
      - ``which``
      - Active or try frame interval, from enum
	:ref:`v4l2_subdev_format_whence <v4l2-subdev-format-whence>`.
    * - __u32
      - ``reserved``\ [7]
      - Reserved for future extensions. Applications and drivers must set
	the array to zero.

@@ -114,9 +119,9 @@ EBUSY
EINVAL
    The struct
    :c:type:`v4l2_subdev_frame_interval`
    ``pad`` references a non-existing pad, or the pad doesn't support
    frame intervals.
    ``pad`` references a non-existing pad, the ``which`` field references a
    non-existing frame interval, or the pad doesn't support frame intervals.

EPERM
    The ``VIDIOC_SUBDEV_S_FRAME_INTERVAL`` ioctl has been called on a read-only
    subdevice.
    subdevice and the ``which`` field is set to ``V4L2_SUBDEV_FORMAT_ACTIVE``.
+7 −0
Original line number Diff line number Diff line
@@ -469,6 +469,13 @@ static int adv7180_get_frame_interval(struct v4l2_subdev *sd,
{
	struct adv7180_state *state = to_state(sd);

	/*
	 * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
	 * subdev active state API.
	 */
	if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE)
		return -EINVAL;

	if (state->curr_norm & V4L2_STD_525_60) {
		fi->interval.numerator = 1001;
		fi->interval.denominator = 30000;
+14 −0
Original line number Diff line number Diff line
@@ -1654,6 +1654,13 @@ static int alvium_g_frame_interval(struct v4l2_subdev *sd,
{
	struct alvium_dev *alvium = sd_to_alvium(sd);

	/*
	 * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
	 * subdev active state API.
	 */
	if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE)
		return -EINVAL;

	fi->interval = alvium->frame_interval;

	return 0;
@@ -1703,6 +1710,13 @@ static int alvium_s_frame_interval(struct v4l2_subdev *sd,
	struct alvium_dev *alvium = sd_to_alvium(sd);
	int ret;

	/*
	 * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
	 * subdev active state API.
	 */
	if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE)
		return -EINVAL;

	if (alvium->streaming)
		return -EBUSY;

+14 −0
Original line number Diff line number Diff line
@@ -1051,6 +1051,13 @@ static int et8ek8_get_frame_interval(struct v4l2_subdev *subdev,
{
	struct et8ek8_sensor *sensor = to_et8ek8_sensor(subdev);

	/*
	 * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
	 * subdev active state API.
	 */
	if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE)
		return -EINVAL;

	memset(fi, 0, sizeof(*fi));
	fi->interval = sensor->current_reglist->mode.timeperframe;

@@ -1064,6 +1071,13 @@ static int et8ek8_set_frame_interval(struct v4l2_subdev *subdev,
	struct et8ek8_sensor *sensor = to_et8ek8_sensor(subdev);
	struct et8ek8_reglist *reglist;

	/*
	 * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
	 * subdev active state API.
	 */
	if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE)
		return -EINVAL;

	reglist = et8ek8_reglist_find_mode_ival(&meta_reglist,
						sensor->current_reglist,
						&fi->interval);
Loading