media: v4l2-subdev: Add which field to struct v4l2_subdev_frame_interval
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Wed, 13 Dec 2023 15:00:05 +0000 (17:00 +0200)
committerHans Verkuil <hverkuil-cisco@xs4all.nl>
Wed, 13 Dec 2023 15:52:35 +0000 (16:52 +0100)
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: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de> # for imx-media
Reviewed-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Reviewed-by: Luca Ceresoli <luca.ceresoli@bootlin.com> # for tegra-video
Reviewed-by: Mauro Carvalho Chehab <mchehab@kernel.org>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
37 files changed:
Documentation/userspace-api/media/v4l/vidioc-subdev-g-client-cap.rst
Documentation/userspace-api/media/v4l/vidioc-subdev-g-frame-interval.rst
drivers/media/i2c/adv7180.c
drivers/media/i2c/alvium-csi2.c
drivers/media/i2c/et8ek8/et8ek8_driver.c
drivers/media/i2c/imx214.c
drivers/media/i2c/imx274.c
drivers/media/i2c/max9286.c
drivers/media/i2c/mt9m111.c
drivers/media/i2c/mt9m114.c
drivers/media/i2c/mt9v011.c
drivers/media/i2c/mt9v111.c
drivers/media/i2c/ov2680.c
drivers/media/i2c/ov5640.c
drivers/media/i2c/ov5648.c
drivers/media/i2c/ov5693.c
drivers/media/i2c/ov6650.c
drivers/media/i2c/ov7251.c
drivers/media/i2c/ov7670.c
drivers/media/i2c/ov772x.c
drivers/media/i2c/ov8865.c
drivers/media/i2c/ov9650.c
drivers/media/i2c/s5c73m3/s5c73m3-core.c
drivers/media/i2c/s5k5baf.c
drivers/media/i2c/thp7312.c
drivers/media/i2c/tvp514x.c
drivers/media/v4l2-core/v4l2-subdev.c
drivers/staging/media/atomisp/i2c/atomisp-gc0310.c
drivers/staging/media/atomisp/i2c/atomisp-gc2235.c
drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c
drivers/staging/media/atomisp/i2c/atomisp-ov2722.c
drivers/staging/media/imx/imx-ic-prp.c
drivers/staging/media/imx/imx-ic-prpencvf.c
drivers/staging/media/imx/imx-media-csi.c
drivers/staging/media/imx/imx-media-vdic.c
drivers/staging/media/tegra-video/csi.c
include/uapi/linux/v4l2-subdev.h

index 20f12a1cc0f7dc8cb9bedb7e1e541c9f671165f6..810b6a859dc8d75897f70657f447147f605e7e5f 100644 (file)
@@ -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
 ============
index 842f962d2aeaf190baa41d72fe5dda57340225c5..41e0e2c8ecc3f3cf908f72e931600d5c481fd059 100644 (file)
@@ -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``.
index 7ed86030fb5c7b45f96dc44c88430a3069fa7a17..409b9a37f0185c7ecf7f0cc91e4fd897d7137eb7 100644 (file)
@@ -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;
index a173abb0509f359a1b9eba02b72b2bd78c76f5a7..34ff7fad38774d428fd8612d64da95486465703d 100644 (file)
@@ -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;
 
index 71fb5aebd3df7b6ad2fd91df130cfc6d4708a4ec..f548b1bb75fb92850cb864526e5d85820e7b2f57 100644 (file)
@@ -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);
index 8e832a4e3544246a0dd5a16f05e2094869b70b44..b148b1bd2bc3b28a3fb658903d01b94d1522635a 100644 (file)
@@ -905,6 +905,13 @@ static int imx214_get_frame_interval(struct v4l2_subdev *subdev,
                                     struct v4l2_subdev_state *sd_state,
                                     struct v4l2_subdev_frame_interval *fival)
 {
+       /*
+        * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+        * subdev active state API.
+        */
+       if (fival->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+               return -EINVAL;
+
        fival->interval.numerator = 1;
        fival->interval.denominator = IMX214_FPS;
 
index 4040c642a36ff8235306253a765028e0797b1c90..352da68b8b41b28828bc5ab04f5e1b331d356eda 100644 (file)
@@ -1333,6 +1333,13 @@ static int imx274_get_frame_interval(struct v4l2_subdev *sd,
 {
        struct stimx274 *imx274 = to_imx274(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 = imx274->frame_interval;
        dev_dbg(&imx274->client->dev, "%s frame rate = %d / %d\n",
                __func__, imx274->frame_interval.numerator,
@@ -1350,6 +1357,13 @@ static int imx274_set_frame_interval(struct v4l2_subdev *sd,
        int min, max, def;
        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;
+
        ret = pm_runtime_resume_and_get(&imx274->client->dev);
        if (ret < 0)
                return ret;
index 7e8cb53d31c3569b665a3fb09d8b208ea0a3d45c..d685d445cf23ae197e148b47b0e55aa875026c4a 100644 (file)
@@ -874,6 +874,13 @@ static int max9286_get_frame_interval(struct v4l2_subdev *sd,
 {
        struct max9286_priv *priv = sd_to_max9286(sd);
 
+       /*
+        * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+        * subdev active state API.
+        */
+       if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+               return -EINVAL;
+
        if (interval->pad != MAX9286_SRC_PAD)
                return -EINVAL;
 
@@ -888,6 +895,13 @@ static int max9286_set_frame_interval(struct v4l2_subdev *sd,
 {
        struct max9286_priv *priv = sd_to_max9286(sd);
 
+       /*
+        * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+        * subdev active state API.
+        */
+       if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+               return -EINVAL;
+
        if (interval->pad != MAX9286_SRC_PAD)
                return -EINVAL;
 
index 602954650f2ebcece3c8afb3e881e50c224c2393..ceeeb94c38d5d2c4225e71c6744e83342e14edaa 100644 (file)
@@ -1051,6 +1051,13 @@ static int mt9m111_get_frame_interval(struct v4l2_subdev *sd,
 {
        struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, 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;
+
        fi->interval = mt9m111->frame_interval;
 
        return 0;
@@ -1068,6 +1075,13 @@ static int mt9m111_set_frame_interval(struct v4l2_subdev *sd,
        if (mt9m111->is_streaming)
                return -EBUSY;
 
+       /*
+        * 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 (fi->pad != 0)
                return -EINVAL;
 
index dcd94299787c822dfdae2113fead0eadb19563c8..427eae13ce26e3bb52980c37ca6efc2f640c4b40 100644 (file)
@@ -1592,6 +1592,13 @@ static int mt9m114_ifp_get_frame_interval(struct v4l2_subdev *sd,
        struct v4l2_fract *ival = &interval->interval;
        struct mt9m114 *sensor = ifp_to_mt9m114(sd);
 
+       /*
+        * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+        * subdev active state API.
+        */
+       if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+               return -EINVAL;
+
        mutex_lock(sensor->ifp.hdl.lock);
 
        ival->numerator = 1;
@@ -1610,6 +1617,13 @@ static int mt9m114_ifp_set_frame_interval(struct v4l2_subdev *sd,
        struct mt9m114 *sensor = ifp_to_mt9m114(sd);
        int ret = 0;
 
+       /*
+        * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+        * subdev active state API.
+        */
+       if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+               return -EINVAL;
+
        mutex_lock(sensor->ifp.hdl.lock);
 
        if (ival->numerator != 0 && ival->denominator != 0)
index 3485761428bacc570575d24174c87f0745c7a486..8834ff8786e598becd362fc7c37aeb37d6df8f49 100644 (file)
@@ -366,6 +366,13 @@ static int mt9v011_get_frame_interval(struct v4l2_subdev *sd,
                                      struct v4l2_subdev_state *sd_state,
                                      struct v4l2_subdev_frame_interval *ival)
 {
+       /*
+        * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+        * subdev active state API.
+        */
+       if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+               return -EINVAL;
+
        calc_fps(sd,
                 &ival->interval.numerator,
                 &ival->interval.denominator);
@@ -380,6 +387,13 @@ static int mt9v011_set_frame_interval(struct v4l2_subdev *sd,
        struct v4l2_fract *tpf = &ival->interval;
        u16 speed;
 
+       /*
+        * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+        * subdev active state API.
+        */
+       if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+               return -EINVAL;
+
        speed = calc_speed(sd, tpf->numerator, tpf->denominator);
 
        mt9v011_write(sd, R0A_MT9V011_CLK_SPEED, speed);
index 496be67c971bacf1c85a1bf0af13e56de8d0f264..b0b98ed3c1502fddf81f5353f7861154ca668e3c 100644 (file)
@@ -730,6 +730,13 @@ static int mt9v111_set_frame_interval(struct v4l2_subdev *sd,
                           tpf->denominator;
        unsigned int max_fps;
 
+       /*
+        * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+        * subdev active state API.
+        */
+       if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+               return -EINVAL;
+
        if (!tpf->numerator)
                tpf->numerator = 1;
 
@@ -779,6 +786,13 @@ static int mt9v111_get_frame_interval(struct v4l2_subdev *sd,
        struct mt9v111_dev *mt9v111 = sd_to_mt9v111(sd);
        struct v4l2_fract *tpf = &ival->interval;
 
+       /*
+        * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+        * subdev active state API.
+        */
+       if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+               return -EINVAL;
+
        mutex_lock(&mt9v111->stream_mutex);
 
        tpf->numerator = 1;
index e3ff64a9e6ca7d1ee589afe062cabee0a92686d6..39d321e2b7f98aa1d581693939b6520ac9811c4d 100644 (file)
@@ -558,6 +558,13 @@ static int ov2680_get_frame_interval(struct v4l2_subdev *sd,
 {
        struct ov2680_dev *sensor = to_ov2680_dev(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;
+
        mutex_lock(&sensor->lock);
        fi->interval = sensor->mode.frame_interval;
        mutex_unlock(&sensor->lock);
index 336bfd1ffd328f1a730222fc817021416541389a..5162d45fe73bd7603b022142b6795ad5e0d28a5b 100644 (file)
@@ -3610,6 +3610,13 @@ static int ov5640_get_frame_interval(struct v4l2_subdev *sd,
 {
        struct ov5640_dev *sensor = to_ov5640_dev(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;
+
        mutex_lock(&sensor->lock);
        fi->interval = sensor->frame_interval;
        mutex_unlock(&sensor->lock);
@@ -3625,6 +3632,13 @@ static int ov5640_set_frame_interval(struct v4l2_subdev *sd,
        const struct ov5640_mode_info *mode;
        int frame_rate, ret = 0;
 
+       /*
+        * 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 (fi->pad != 0)
                return -EINVAL;
 
index d0d7e9968f4856dd96a7bf88b45a777d7c134f56..4b86d2631bd1cd19e6d5c9b8b3d0a1f9c48aeab7 100644 (file)
@@ -2276,6 +2276,13 @@ static int ov5648_get_frame_interval(struct v4l2_subdev *subdev,
        const struct ov5648_mode *mode;
        int ret = 0;
 
+       /*
+        * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+        * subdev active state API.
+        */
+       if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+               return -EINVAL;
+
        mutex_lock(&sensor->mutex);
 
        mode = sensor->state.mode;
index a65645811fbcb4ed497ec3aa469856f02427c582..8deb28b55983e976ea36c4efd1778353088b01e6 100644 (file)
@@ -1013,6 +1013,13 @@ static int ov5693_get_frame_interval(struct v4l2_subdev *sd,
                                 ov5693->ctrls.vblank->val);
        unsigned int fps = DIV_ROUND_CLOSEST(OV5693_PIXEL_RATE, framesize);
 
+       /*
+        * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+        * subdev active state API.
+        */
+       if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+               return -EINVAL;
+
        interval->interval.numerator = 1;
        interval->interval.denominator = fps;
 
index a4dc45bdf3d7c0da00d4c9332f3c6c5c095c3570..b65befb22a7916a38b44fb3fbd453f3b16f988aa 100644 (file)
@@ -806,6 +806,13 @@ static int ov6650_get_frame_interval(struct v4l2_subdev *sd,
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct ov6650 *priv = to_ov6650(client);
 
+       /*
+        * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+        * subdev active state API.
+        */
+       if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+               return -EINVAL;
+
        ival->interval = priv->tpf;
 
        dev_dbg(&client->dev, "Frame interval: %u/%u s\n",
@@ -823,6 +830,13 @@ static int ov6650_set_frame_interval(struct v4l2_subdev *sd,
        struct v4l2_fract *tpf = &ival->interval;
        int div, ret;
 
+       /*
+        * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+        * subdev active state API.
+        */
+       if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+               return -EINVAL;
+
        if (tpf->numerator == 0 || tpf->denominator == 0)
                div = 1;  /* Reset to full rate */
        else
index 10d6b5deed83bc8e1d80c16a0a333f2f47e49775..30f61e04ecaf51545b5251ba6ac8ef7470d8a245 100644 (file)
@@ -1391,6 +1391,13 @@ static int ov7251_get_frame_interval(struct v4l2_subdev *subdev,
 {
        struct ov7251 *ov7251 = to_ov7251(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;
+
        mutex_lock(&ov7251->lock);
        fi->interval = ov7251->current_mode->timeperframe;
        mutex_unlock(&ov7251->lock);
@@ -1406,6 +1413,13 @@ static int ov7251_set_frame_interval(struct v4l2_subdev *subdev,
        const struct ov7251_mode_info *new_mode;
        int ret = 0;
 
+       /*
+        * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+        * subdev active state API.
+        */
+       if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+               return -EINVAL;
+
        mutex_lock(&ov7251->lock);
        new_mode = ov7251_find_mode_by_ival(ov7251, &fi->interval);
 
index 463f20ece36e5be7c3a5086ab59093da8068f03a..0cb96b6c99905c3b9112568671c8e047c9723876 100644 (file)
@@ -1160,6 +1160,12 @@ static int ov7670_get_frame_interval(struct v4l2_subdev *sd,
 {
        struct ov7670_info *info = to_state(sd);
 
+       /*
+        * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+        * subdev active state API.
+        */
+       if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+               return -EINVAL;
 
        info->devtype->get_framerate(sd, &ival->interval);
 
@@ -1173,6 +1179,12 @@ static int ov7670_set_frame_interval(struct v4l2_subdev *sd,
        struct v4l2_fract *tpf = &ival->interval;
        struct ov7670_info *info = to_state(sd);
 
+       /*
+        * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+        * subdev active state API.
+        */
+       if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+               return -EINVAL;
 
        return info->devtype->set_framerate(sd, tpf);
 }
index a14a25946c5b3b12a1c2e97614e9c3ac20019428..3e36a55274efb2aa5fe160f046b51f4ff584cdd0 100644 (file)
@@ -724,6 +724,13 @@ static int ov772x_get_frame_interval(struct v4l2_subdev *sd,
        struct ov772x_priv *priv = to_ov772x(sd);
        struct v4l2_fract *tpf = &ival->interval;
 
+       /*
+        * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+        * subdev active state API.
+        */
+       if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+               return -EINVAL;
+
        tpf->numerator = 1;
        tpf->denominator = priv->fps;
 
@@ -739,6 +746,13 @@ static int ov772x_set_frame_interval(struct v4l2_subdev *sd,
        unsigned int fps;
        int ret = 0;
 
+       /*
+        * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+        * subdev active state API.
+        */
+       if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+               return -EINVAL;
+
        mutex_lock(&priv->lock);
 
        if (priv->streaming) {
index 02a595281c49e7243a280aa8e0ace9c5609b1fa0..95ffe7536aa6aba814f4e5c3d12e7279470b2f07 100644 (file)
@@ -2846,6 +2846,13 @@ static int ov8865_get_frame_interval(struct v4l2_subdev *subdev,
        unsigned int framesize;
        unsigned int fps;
 
+       /*
+        * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+        * subdev active state API.
+        */
+       if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+               return -EINVAL;
+
        mutex_lock(&sensor->mutex);
 
        mode = sensor->state.mode;
index f528892c893f239154a9aabe53ed4238d6be1b32..66cd0e9ddc9ab81e3b9756bc236bb78095a44f55 100644 (file)
@@ -1107,6 +1107,13 @@ static int ov965x_get_frame_interval(struct v4l2_subdev *sd,
 {
        struct ov965x *ov965x = to_ov965x(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;
+
        mutex_lock(&ov965x->lock);
        fi->interval = ov965x->fiv->interval;
        mutex_unlock(&ov965x->lock);
@@ -1156,6 +1163,13 @@ static int ov965x_set_frame_interval(struct v4l2_subdev *sd,
        struct ov965x *ov965x = to_ov965x(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;
+
        v4l2_dbg(1, debug, sd, "Setting %d/%d frame interval\n",
                 fi->interval.numerator, fi->interval.denominator);
 
index 73ca50f498122029412136215ce3bbc1ddd678f1..af8d01f78c32adea456e037aaa92564ad7dd8f22 100644 (file)
@@ -872,6 +872,13 @@ static int s5c73m3_oif_get_frame_interval(struct v4l2_subdev *sd,
 {
        struct s5c73m3 *state = oif_sd_to_s5c73m3(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 (fi->pad != OIF_SOURCE_PAD)
                return -EINVAL;
 
@@ -923,6 +930,13 @@ static int s5c73m3_oif_set_frame_interval(struct v4l2_subdev *sd,
        struct s5c73m3 *state = oif_sd_to_s5c73m3(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 (fi->pad != OIF_SOURCE_PAD)
                return -EINVAL;
 
index 2fd1ecfeb0868f03222f5a3cea1c1f4e04e68ba1..de079d2c9282b18220787bd48a3840f8631b2a57 100644 (file)
@@ -1124,6 +1124,13 @@ static int s5k5baf_get_frame_interval(struct v4l2_subdev *sd,
 {
        struct s5k5baf *state = to_s5k5baf(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;
+
        mutex_lock(&state->lock);
        fi->interval.numerator = state->fiv;
        fi->interval.denominator = 10000;
@@ -1162,6 +1169,13 @@ static int s5k5baf_set_frame_interval(struct v4l2_subdev *sd,
 {
        struct s5k5baf *state = to_s5k5baf(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;
+
        mutex_lock(&state->lock);
        __s5k5baf_set_frame_interval(state, fi);
        mutex_unlock(&state->lock);
index d4975b180704a73c9d1b58d92fad378f26c345e1..ad4f2b794e1a3ed27f72977a191e4bc18aa6e57e 100644 (file)
@@ -740,6 +740,13 @@ static int thp7312_get_frame_interval(struct v4l2_subdev *sd,
 {
        struct thp7312_device *thp7312 = to_thp7312_dev(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.numerator = 1;
        fi->interval.denominator = thp7312->current_rate->fps;
 
@@ -757,6 +764,13 @@ static int thp7312_set_frame_interval(struct v4l2_subdev *sd,
        unsigned int best_delta = UINT_MAX;
        unsigned int fps;
 
+       /*
+        * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+        * subdev active state API.
+        */
+       if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+               return -EINVAL;
+
        /* Avoid divisions by 0, pick the highest frame if the interval is 0. */
        fps = fi->interval.numerator
            ? DIV_ROUND_CLOSEST(fi->interval.denominator, fi->interval.numerator)
index dee0cf992379241cb754b5ce8c2c5e39d51dcc69..5a561e5bf65981effcb73ad5a98af1ae4a587c86 100644 (file)
@@ -746,6 +746,12 @@ tvp514x_get_frame_interval(struct v4l2_subdev *sd,
        struct tvp514x_decoder *decoder = to_decoder(sd);
        enum tvp514x_std current_std;
 
+       /*
+        * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+        * subdev active state API.
+        */
+       if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+               return -EINVAL;
 
        /* get the current standard */
        current_std = decoder->current_std;
@@ -765,6 +771,12 @@ tvp514x_set_frame_interval(struct v4l2_subdev *sd,
        struct v4l2_fract *timeperframe;
        enum tvp514x_std current_std;
 
+       /*
+        * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+        * subdev active state API.
+        */
+       if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+               return -EINVAL;
 
        timeperframe = &ival->interval;
 
index 405a4a2fa565b90d184b820c093ae626fcee962c..30131a37f2d582c8432fc06bfbb618c200e65e05 100644 (file)
@@ -291,9 +291,8 @@ static inline int check_frame_interval(struct v4l2_subdev *sd,
        if (!fi)
                return -EINVAL;
 
-       return check_pad(sd, fi->pad) ? :
-              check_state(sd, state, V4L2_SUBDEV_FORMAT_ACTIVE, fi->pad,
-                          fi->stream);
+       return check_which(fi->which) ? : check_pad(sd, fi->pad) ? :
+              check_state(sd, state, fi->which, fi->pad, fi->stream);
 }
 
 static int call_get_frame_interval(struct v4l2_subdev *sd,
@@ -537,9 +536,16 @@ subdev_ioctl_get_state(struct v4l2_subdev *sd, struct v4l2_subdev_fh *subdev_fh,
                which = ((struct v4l2_subdev_selection *)arg)->which;
                break;
        case VIDIOC_SUBDEV_G_FRAME_INTERVAL:
-       case VIDIOC_SUBDEV_S_FRAME_INTERVAL:
-               which = V4L2_SUBDEV_FORMAT_ACTIVE;
+       case VIDIOC_SUBDEV_S_FRAME_INTERVAL: {
+               struct v4l2_subdev_frame_interval *fi = arg;
+
+               if (!(subdev_fh->client_caps &
+                     V4L2_SUBDEV_CLIENT_CAP_INTERVAL_USES_WHICH))
+                       fi->which = V4L2_SUBDEV_FORMAT_ACTIVE;
+
+               which = fi->which;
                break;
+       }
        case VIDIOC_SUBDEV_G_ROUTING:
        case VIDIOC_SUBDEV_S_ROUTING:
                which = ((struct v4l2_subdev_routing *)arg)->which;
@@ -796,12 +802,12 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg,
        case VIDIOC_SUBDEV_S_FRAME_INTERVAL: {
                struct v4l2_subdev_frame_interval *fi = arg;
 
-               if (ro_subdev)
-                       return -EPERM;
-
                if (!client_supports_streams)
                        fi->stream = 0;
 
+               if (fi->which != V4L2_SUBDEV_FORMAT_TRY && ro_subdev)
+                       return -EPERM;
+
                memset(fi->reserved, 0, sizeof(fi->reserved));
                return v4l2_subdev_call(sd, pad, set_frame_interval, state, fi);
        }
@@ -998,7 +1004,8 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg,
                        client_cap->capabilities &= ~V4L2_SUBDEV_CLIENT_CAP_STREAMS;
 
                /* Filter out unsupported capabilities */
-               client_cap->capabilities &= V4L2_SUBDEV_CLIENT_CAP_STREAMS;
+               client_cap->capabilities &= (V4L2_SUBDEV_CLIENT_CAP_STREAMS |
+                                            V4L2_SUBDEV_CLIENT_CAP_INTERVAL_USES_WHICH);
 
                subdev_fh->client_caps = client_cap->capabilities;
 
index 006e8adac47b0b5c16fb3f18578a73592a027f2a..5bcd634a2a44dfaed14d58f66b705c0567440982 100644 (file)
@@ -500,6 +500,13 @@ static int gc0310_get_frame_interval(struct v4l2_subdev *sd,
                                     struct v4l2_subdev_state *sd_state,
                                     struct v4l2_subdev_frame_interval *interval)
 {
+       /*
+        * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+        * subdev active state API.
+        */
+       if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+               return -EINVAL;
+
        interval->interval.numerator = 1;
        interval->interval.denominator = GC0310_FPS;
 
index aa257322a7000d6e2e3fa077baf2d9566748ba42..bec4c5615864091b9a88adf0ddb0cc71d2430456 100644 (file)
@@ -704,6 +704,13 @@ static int gc2235_get_frame_interval(struct v4l2_subdev *sd,
 {
        struct gc2235_device *dev = to_gc2235_sensor(sd);
 
+       /*
+        * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+        * subdev active state API.
+        */
+       if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+               return -EINVAL;
+
        interval->interval.numerator = 1;
        interval->interval.denominator = dev->res->fps;
 
index 459c5b8233cee4b103f4ab65a6c74c78678c4910..20f02d18a8de14d3a911797431f548fda937ff20 100644 (file)
@@ -1394,6 +1394,13 @@ static int mt9m114_get_frame_interval(struct v4l2_subdev *sd,
 {
        struct mt9m114_device *dev = to_mt9m114_sensor(sd);
 
+       /*
+        * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+        * subdev active state API.
+        */
+       if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+               return -EINVAL;
+
        interval->interval.numerator = 1;
        interval->interval.denominator = mt9m114_res[dev->res].fps;
 
index b3ef04d7ccca7833e2900fc60cef91e183f9cacd..133e346ae51b08c5a5913e89e97a146db69fd080 100644 (file)
@@ -851,6 +851,13 @@ static int ov2722_get_frame_interval(struct v4l2_subdev *sd,
 {
        struct ov2722_device *dev = to_ov2722_sensor(sd);
 
+       /*
+        * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+        * subdev active state API.
+        */
+       if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+               return -EINVAL;
+
        interval->interval.numerator = 1;
        interval->interval.denominator = dev->res->fps;
 
index fb96f87e664edca1406c15f8ee587d401aff9568..2b80d54006b39695d01d3f8e6d02c0e07569217d 100644 (file)
@@ -399,6 +399,13 @@ static int prp_get_frame_interval(struct v4l2_subdev *sd,
 {
        struct prp_priv *priv = sd_to_priv(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 (fi->pad >= PRP_NUM_PADS)
                return -EINVAL;
 
@@ -415,6 +422,13 @@ static int prp_set_frame_interval(struct v4l2_subdev *sd,
 {
        struct prp_priv *priv = sd_to_priv(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 (fi->pad >= PRP_NUM_PADS)
                return -EINVAL;
 
index 7bfe433cd3228cdbaffd3c64950a8cd9a8bbb387..17fd980c9d3c3c0e868670ca863290f83f13d9c6 100644 (file)
@@ -1209,6 +1209,13 @@ static int prp_get_frame_interval(struct v4l2_subdev *sd,
 {
        struct prp_priv *priv = sd_to_priv(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 (fi->pad >= PRPENCVF_NUM_PADS)
                return -EINVAL;
 
@@ -1225,6 +1232,13 @@ static int prp_set_frame_interval(struct v4l2_subdev *sd,
 {
        struct prp_priv *priv = sd_to_priv(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 (fi->pad >= PRPENCVF_NUM_PADS)
                return -EINVAL;
 
index 4308fdc9b58e2a77add0a4dd465f54d603601203..785aac88192212bcb31d6145522f5ebb2b356feb 100644 (file)
@@ -908,6 +908,13 @@ static int csi_get_frame_interval(struct v4l2_subdev *sd,
 {
        struct csi_priv *priv = v4l2_get_subdevdata(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 (fi->pad >= CSI_NUM_PADS)
                return -EINVAL;
 
@@ -928,6 +935,13 @@ static int csi_set_frame_interval(struct v4l2_subdev *sd,
        struct v4l2_fract *input_fi;
        int ret = 0;
 
+       /*
+        * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+        * subdev active state API.
+        */
+       if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+               return -EINVAL;
+
        mutex_lock(&priv->lock);
 
        input_fi = &priv->frame_interval[CSI_SINK_PAD];
index a51b3767923961c3cb53f142ec3d4c46ac956fd4..09da4103a8dbedfd02c60804c73a6259f2b3ac8a 100644 (file)
@@ -786,6 +786,13 @@ static int vdic_get_frame_interval(struct v4l2_subdev *sd,
 {
        struct vdic_priv *priv = v4l2_get_subdevdata(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 (fi->pad >= VDIC_NUM_PADS)
                return -EINVAL;
 
@@ -806,6 +813,13 @@ static int vdic_set_frame_interval(struct v4l2_subdev *sd,
        struct v4l2_fract *input_fi, *output_fi;
        int ret = 0;
 
+       /*
+        * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+        * subdev active state API.
+        */
+       if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+               return -EINVAL;
+
        mutex_lock(&priv->lock);
 
        input_fi = &priv->frame_interval[priv->active_input_pad];
index b1b666179be5257da8613819ed19652a795902cc..255cccd0c5fda8e47455142451f56d27bcd7a608 100644 (file)
@@ -231,6 +231,13 @@ static int tegra_csi_get_frame_interval(struct v4l2_subdev *subdev,
        if (!IS_ENABLED(CONFIG_VIDEO_TEGRA_TPG))
                return -ENOIOCTLCMD;
 
+       /*
+        * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+        * subdev active state API.
+        */
+       if (vfi->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+               return -EINVAL;
+
        vfi->interval.numerator = 1;
        vfi->interval.denominator = csi_chan->framerate;
 
index f0fbb4a7c15069ea672b67cb396e2ccf8d9719d3..7048c51581c6ec61be49d1e20d783b3174a48c14 100644 (file)
@@ -116,13 +116,15 @@ struct v4l2_subdev_frame_size_enum {
  * @pad: pad number, as reported by the media API
  * @interval: frame interval in seconds
  * @stream: stream number, defined in subdev routing
+ * @which: interval type (from enum v4l2_subdev_format_whence)
  * @reserved: drivers and applications must zero this array
  */
 struct v4l2_subdev_frame_interval {
        __u32 pad;
        struct v4l2_fract interval;
        __u32 stream;
-       __u32 reserved[8];
+       __u32 which;
+       __u32 reserved[7];
 };
 
 /**
@@ -133,7 +135,7 @@ struct v4l2_subdev_frame_interval {
  * @width: frame width in pixels
  * @height: frame height in pixels
  * @interval: frame interval in seconds
- * @which: format type (from enum v4l2_subdev_format_whence)
+ * @which: interval type (from enum v4l2_subdev_format_whence)
  * @stream: stream number, defined in subdev routing
  * @reserved: drivers and applications must zero this array
  */
@@ -239,7 +241,14 @@ struct v4l2_subdev_routing {
  * set (which is the default), the 'stream' fields will be forced to 0 by the
  * kernel.
  */
-#define V4L2_SUBDEV_CLIENT_CAP_STREAMS         (1ULL << 0)
+#define V4L2_SUBDEV_CLIENT_CAP_STREAMS                 (1ULL << 0)
+
+/*
+ * The client is aware of the struct 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.
+ */
+#define V4L2_SUBDEV_CLIENT_CAP_INTERVAL_USES_WHICH     (1ULL << 1)
 
 /**
  * struct v4l2_subdev_client_capability - Capabilities of the client accessing