From patchwork Tue Oct 24 00:51:27 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 13433794 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id F1AEAC00A8F for ; Tue, 24 Oct 2023 00:51:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231725AbjJXAvk (ORCPT ); Mon, 23 Oct 2023 20:51:40 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39504 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231713AbjJXAvc (ORCPT ); Mon, 23 Oct 2023 20:51:32 -0400 Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A2F8B9B for ; Mon, 23 Oct 2023 17:51:25 -0700 (PDT) Received: from pendragon.ideasonboard.com (213-243-189-158.bb.dnainternet.fi [213.243.189.158]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 3DB6C3D6; Tue, 24 Oct 2023 02:51:13 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1698108673; bh=bWgK3h83aR7itiYmj37Mwh0so1HA6o9Jk37yOBrs+ZU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=pn+eFtG1Ve5rGQIulFxiw+nR6hSFnf5FbEeAwMA0t3bVxZBSUh7Aso1baP8lgUfsL t3YM18ldR7HVjpOphQwgqwwjKJ6zagEt/MkZisbEUys/PJCSh/YaWroung9NEKk8tq 1rqPaHjGhxR01Y6DMVOPAgoVxQSOTCP+7U95Et7U= From: Laurent Pinchart To: linux-media@vger.kernel.org Cc: Sakari Ailus , Hans Verkuil , Tomi Valkeinen , Hans de Goede Subject: [RFC PATCH v1 1/4] media: v4l2-subdev: Turn .[gs]_frame_interval into pad operations Date: Tue, 24 Oct 2023 03:51:27 +0300 Message-ID: <20231024005130.28026-2-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20231024005130.28026-1-laurent.pinchart@ideasonboard.com> References: <20231024005130.28026-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org The subdev .[gs]_frame_interval are video operations, but they operate on pads (and even on streams). Not only is this confusing, it causes practical issues for drivers as the operations don't receive a subdev state pointer, requiring manual state handling. To improve the situation, turn the operations into pad operations, and extend them to receive a state pointer like other pad operations. While at it, rename the operations to .[gs]et_frame_interval at the same time to match the naming scheme of other pad operations. This isn't strictly necessary, but given that all drivers using those operations need to be modified, handling the rename separately would generate more churn for very little gain (if at all). Signed-off-by: Laurent Pinchart --- drivers/media/i2c/adv7180.c | 7 ++- drivers/media/i2c/et8ek8/et8ek8_driver.c | 6 +- drivers/media/i2c/imx214.c | 9 +-- drivers/media/i2c/imx274.c | 48 +++++--------- drivers/media/i2c/max9286.c | 14 +++-- drivers/media/i2c/mt9m111.c | 14 +++-- drivers/media/i2c/mt9m114.c | 14 +++-- drivers/media/i2c/mt9v011.c | 18 +++--- drivers/media/i2c/mt9v111.c | 16 ++--- drivers/media/i2c/ov2680.c | 7 ++- drivers/media/i2c/ov5640.c | 16 ++--- drivers/media/i2c/ov5648.c | 59 ++++++++--------- drivers/media/i2c/ov5693.c | 7 ++- drivers/media/i2c/ov6650.c | 16 ++--- drivers/media/i2c/ov7251.c | 6 +- drivers/media/i2c/ov7670.c | 18 +++--- drivers/media/i2c/ov772x.c | 14 +++-- drivers/media/i2c/ov7740.c | 40 +++++------- drivers/media/i2c/ov8865.c | 51 +++++++-------- drivers/media/i2c/ov9650.c | 14 +++-- drivers/media/i2c/s5c73m3/s5c73m3-core.c | 14 +++-- drivers/media/i2c/s5k5baf.c | 20 +++--- drivers/media/i2c/tvp514x.c | 29 +++------ drivers/media/usb/em28xx/em28xx-video.c | 6 +- drivers/media/v4l2-core/v4l2-common.c | 8 +-- drivers/media/v4l2-core/v4l2-subdev.c | 63 +++++++++++-------- .../media/atomisp/i2c/atomisp-gc0310.c | 7 ++- .../media/atomisp/i2c/atomisp-gc2235.c | 7 ++- .../media/atomisp/i2c/atomisp-mt9m114.c | 7 ++- .../media/atomisp/i2c/atomisp-ov2722.c | 7 ++- .../staging/media/atomisp/pci/atomisp_cmd.c | 4 +- .../staging/media/atomisp/pci/atomisp_ioctl.c | 4 +- drivers/staging/media/imx/imx-ic-prp.c | 14 +++-- drivers/staging/media/imx/imx-ic-prpencvf.c | 14 +++-- drivers/staging/media/imx/imx-media-capture.c | 6 +- drivers/staging/media/imx/imx-media-csi.c | 14 +++-- drivers/staging/media/imx/imx-media-vdic.c | 14 +++-- drivers/staging/media/tegra-video/csi.c | 9 +-- include/media/v4l2-common.h | 4 +- include/media/v4l2-subdev.h | 22 ++++--- 40 files changed, 340 insertions(+), 327 deletions(-) diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index 54134473186b..1bd8d9bbb82c 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c @@ -463,8 +463,9 @@ static int adv7180_g_std(struct v4l2_subdev *sd, v4l2_std_id *norm) return 0; } -static int adv7180_g_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *fi) +static int adv7180_get_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *fi) { struct adv7180_state *state = to_state(sd); @@ -913,7 +914,6 @@ static int adv7180_subscribe_event(struct v4l2_subdev *sd, static const struct v4l2_subdev_video_ops adv7180_video_ops = { .s_std = adv7180_s_std, .g_std = adv7180_g_std, - .g_frame_interval = adv7180_g_frame_interval, .querystd = adv7180_querystd, .g_input_status = adv7180_g_input_status, .s_routing = adv7180_s_routing, @@ -933,6 +933,7 @@ static const struct v4l2_subdev_pad_ops adv7180_pad_ops = { .enum_mbus_code = adv7180_enum_mbus_code, .set_fmt = adv7180_set_pad_format, .get_fmt = adv7180_get_pad_format, + .get_frame_interval = adv7180_get_frame_interval, .get_mbus_config = adv7180_get_mbus_config, }; diff --git a/drivers/media/i2c/et8ek8/et8ek8_driver.c b/drivers/media/i2c/et8ek8/et8ek8_driver.c index d6fc843f9368..949859aff1ec 100644 --- a/drivers/media/i2c/et8ek8/et8ek8_driver.c +++ b/drivers/media/i2c/et8ek8/et8ek8_driver.c @@ -1047,6 +1047,7 @@ static int et8ek8_set_pad_format(struct v4l2_subdev *subdev, } static int et8ek8_get_frame_interval(struct v4l2_subdev *subdev, + struct v4l2_subdev_state *sd_state, struct v4l2_subdev_frame_interval *fi) { struct et8ek8_sensor *sensor = to_et8ek8_sensor(subdev); @@ -1058,6 +1059,7 @@ static int et8ek8_get_frame_interval(struct v4l2_subdev *subdev, } static int et8ek8_set_frame_interval(struct v4l2_subdev *subdev, + struct v4l2_subdev_state *sd_state, struct v4l2_subdev_frame_interval *fi) { struct et8ek8_sensor *sensor = to_et8ek8_sensor(subdev); @@ -1343,8 +1345,6 @@ static int et8ek8_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) static const struct v4l2_subdev_video_ops et8ek8_video_ops = { .s_stream = et8ek8_s_stream, - .g_frame_interval = et8ek8_get_frame_interval, - .s_frame_interval = et8ek8_set_frame_interval, }; static const struct v4l2_subdev_core_ops et8ek8_core_ops = { @@ -1357,6 +1357,8 @@ static const struct v4l2_subdev_pad_ops et8ek8_pad_ops = { .enum_frame_interval = et8ek8_enum_frame_ival, .get_fmt = et8ek8_get_pad_format, .set_fmt = et8ek8_set_pad_format, + .get_frame_interval = et8ek8_get_frame_interval, + .set_frame_interval = et8ek8_set_frame_interval, }; static const struct v4l2_subdev_ops et8ek8_ops = { diff --git a/drivers/media/i2c/imx214.c b/drivers/media/i2c/imx214.c index 4f77ea02cc27..c84de2700c0c 100644 --- a/drivers/media/i2c/imx214.c +++ b/drivers/media/i2c/imx214.c @@ -795,8 +795,9 @@ static int imx214_s_stream(struct v4l2_subdev *subdev, int enable) return ret; } -static int imx214_g_frame_interval(struct v4l2_subdev *subdev, - struct v4l2_subdev_frame_interval *fival) +static int imx214_get_frame_interval(struct v4l2_subdev *subdev, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *fival) { fival->interval.numerator = 1; fival->interval.denominator = IMX214_FPS; @@ -828,8 +829,6 @@ static int imx214_enum_frame_interval(struct v4l2_subdev *subdev, static const struct v4l2_subdev_video_ops imx214_video_ops = { .s_stream = imx214_s_stream, - .g_frame_interval = imx214_g_frame_interval, - .s_frame_interval = imx214_g_frame_interval, }; static const struct v4l2_subdev_pad_ops imx214_subdev_pad_ops = { @@ -839,6 +838,8 @@ static const struct v4l2_subdev_pad_ops imx214_subdev_pad_ops = { .get_fmt = imx214_get_format, .set_fmt = imx214_set_format, .get_selection = imx214_get_selection, + .get_frame_interval = imx214_get_frame_interval, + .set_frame_interval = imx214_get_frame_interval, .init_cfg = imx214_entity_init_cfg, }; diff --git a/drivers/media/i2c/imx274.c b/drivers/media/i2c/imx274.c index 1886eaab1c24..444a5a6d22cd 100644 --- a/drivers/media/i2c/imx274.c +++ b/drivers/media/i2c/imx274.c @@ -594,8 +594,8 @@ static int imx274_set_gain(struct stimx274 *priv, struct v4l2_ctrl *ctrl); static int imx274_set_exposure(struct stimx274 *priv, int val); static int imx274_set_vflip(struct stimx274 *priv, int val); static int imx274_set_test_pattern(struct stimx274 *priv, int val); -static int imx274_set_frame_interval(struct stimx274 *priv, - struct v4l2_fract frame_interval); +static int __imx274_set_frame_interval(struct stimx274 *priv, + struct v4l2_fract frame_interval); static inline void msleep_range(unsigned int delay_base) { @@ -1327,17 +1327,9 @@ static int imx274_apply_trimming(struct stimx274 *imx274) return err; } -/** - * imx274_g_frame_interval - Get the frame interval - * @sd: Pointer to V4L2 Sub device structure - * @fi: Pointer to V4l2 Sub device frame interval structure - * - * This function is used to get the frame interval. - * - * Return: 0 on success - */ -static int imx274_g_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *fi) +static int imx274_get_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *fi) { struct stimx274 *imx274 = to_imx274(sd); @@ -1349,17 +1341,9 @@ static int imx274_g_frame_interval(struct v4l2_subdev *sd, return 0; } -/** - * imx274_s_frame_interval - Set the frame interval - * @sd: Pointer to V4L2 Sub device structure - * @fi: Pointer to V4l2 Sub device frame interval structure - * - * This function is used to set the frame intervavl. - * - * Return: 0 on success - */ -static int imx274_s_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *fi) +static int imx274_set_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *fi) { struct stimx274 *imx274 = to_imx274(sd); struct v4l2_ctrl *ctrl = imx274->ctrls.exposure; @@ -1371,7 +1355,7 @@ static int imx274_s_frame_interval(struct v4l2_subdev *sd, return ret; mutex_lock(&imx274->lock); - ret = imx274_set_frame_interval(imx274, fi->interval); + ret = __imx274_set_frame_interval(imx274, fi->interval); if (!ret) { fi->interval = imx274->frame_interval; @@ -1466,8 +1450,8 @@ static int imx274_s_stream(struct v4l2_subdev *sd, int on) * are changed. * gain is not affected. */ - ret = imx274_set_frame_interval(imx274, - imx274->frame_interval); + ret = __imx274_set_frame_interval(imx274, + imx274->frame_interval); if (ret) goto fail; @@ -1830,7 +1814,7 @@ static int imx274_set_frame_length(struct stimx274 *priv, u32 val) } /* - * imx274_set_frame_interval - Function called when setting frame interval + * __imx274_set_frame_interval - Function called when setting frame interval * @priv: Pointer to device structure * @frame_interval: Variable for frame interval * @@ -1839,8 +1823,8 @@ static int imx274_set_frame_length(struct stimx274 *priv, u32 val) * * Return: 0 on success */ -static int imx274_set_frame_interval(struct stimx274 *priv, - struct v4l2_fract frame_interval) +static int __imx274_set_frame_interval(struct stimx274 *priv, + struct v4l2_fract frame_interval) { int err; u32 frame_length, req_frame_rate; @@ -1927,11 +1911,11 @@ static const struct v4l2_subdev_pad_ops imx274_pad_ops = { .set_fmt = imx274_set_fmt, .get_selection = imx274_get_selection, .set_selection = imx274_set_selection, + .get_frame_interval = imx274_get_frame_interval, + .set_frame_interval = imx274_set_frame_interval, }; static const struct v4l2_subdev_video_ops imx274_video_ops = { - .g_frame_interval = imx274_g_frame_interval, - .s_frame_interval = imx274_s_frame_interval, .s_stream = imx274_s_stream, }; diff --git a/drivers/media/i2c/max9286.c b/drivers/media/i2c/max9286.c index fc1cf196ef01..ccf615a12b4f 100644 --- a/drivers/media/i2c/max9286.c +++ b/drivers/media/i2c/max9286.c @@ -868,8 +868,9 @@ static int max9286_s_stream(struct v4l2_subdev *sd, int enable) return 0; } -static int max9286_g_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *interval) +static int max9286_get_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *interval) { struct max9286_priv *priv = sd_to_max9286(sd); @@ -881,8 +882,9 @@ static int max9286_g_frame_interval(struct v4l2_subdev *sd, return 0; } -static int max9286_s_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *interval) +static int max9286_set_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *interval) { struct max9286_priv *priv = sd_to_max9286(sd); @@ -983,14 +985,14 @@ static int max9286_get_fmt(struct v4l2_subdev *sd, static const struct v4l2_subdev_video_ops max9286_video_ops = { .s_stream = max9286_s_stream, - .g_frame_interval = max9286_g_frame_interval, - .s_frame_interval = max9286_s_frame_interval, }; static const struct v4l2_subdev_pad_ops max9286_pad_ops = { .enum_mbus_code = max9286_enum_mbus_code, .get_fmt = max9286_get_fmt, .set_fmt = max9286_set_fmt, + .get_frame_interval = max9286_get_frame_interval, + .set_frame_interval = max9286_set_frame_interval, }; static const struct v4l2_subdev_ops max9286_subdev_ops = { diff --git a/drivers/media/i2c/mt9m111.c b/drivers/media/i2c/mt9m111.c index e17ff41ebba0..c96ad4f58a88 100644 --- a/drivers/media/i2c/mt9m111.c +++ b/drivers/media/i2c/mt9m111.c @@ -1045,8 +1045,9 @@ static const struct v4l2_subdev_core_ops mt9m111_subdev_core_ops = { #endif }; -static int mt9m111_g_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *fi) +static int mt9m111_get_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *fi) { struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev); @@ -1055,8 +1056,9 @@ static int mt9m111_g_frame_interval(struct v4l2_subdev *sd, return 0; } -static int mt9m111_s_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *fi) +static int mt9m111_set_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *fi) { struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev); const struct mt9m111_mode_info *mode; @@ -1151,8 +1153,6 @@ static int mt9m111_get_mbus_config(struct v4l2_subdev *sd, static const struct v4l2_subdev_video_ops mt9m111_subdev_video_ops = { .s_stream = mt9m111_s_stream, - .g_frame_interval = mt9m111_g_frame_interval, - .s_frame_interval = mt9m111_s_frame_interval, }; static const struct v4l2_subdev_pad_ops mt9m111_subdev_pad_ops = { @@ -1162,6 +1162,8 @@ static const struct v4l2_subdev_pad_ops mt9m111_subdev_pad_ops = { .set_selection = mt9m111_set_selection, .get_fmt = mt9m111_get_fmt, .set_fmt = mt9m111_set_fmt, + .get_frame_interval = mt9m111_get_frame_interval, + .set_frame_interval = mt9m111_set_frame_interval, .get_mbus_config = mt9m111_get_mbus_config, }; diff --git a/drivers/media/i2c/mt9m114.c b/drivers/media/i2c/mt9m114.c index ac19078ceda3..c48e6e0e9292 100644 --- a/drivers/media/i2c/mt9m114.c +++ b/drivers/media/i2c/mt9m114.c @@ -1581,8 +1581,9 @@ static int mt9m114_ifp_s_stream(struct v4l2_subdev *sd, int enable) return ret; } -static int mt9m114_ifp_g_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *interval) +static int mt9m114_ifp_get_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *interval) { struct v4l2_fract *ival = &interval->interval; struct mt9m114 *sensor = ifp_to_mt9m114(sd); @@ -1597,8 +1598,9 @@ static int mt9m114_ifp_g_frame_interval(struct v4l2_subdev *sd, return 0; } -static int mt9m114_ifp_s_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *interval) +static int mt9m114_ifp_set_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *interval) { struct v4l2_fract *ival = &interval->interval; struct mt9m114 *sensor = ifp_to_mt9m114(sd); @@ -1963,8 +1965,6 @@ static int mt9m114_ifp_registered(struct v4l2_subdev *sd) static const struct v4l2_subdev_video_ops mt9m114_ifp_video_ops = { .s_stream = mt9m114_ifp_s_stream, - .g_frame_interval = mt9m114_ifp_g_frame_interval, - .s_frame_interval = mt9m114_ifp_s_frame_interval, }; static const struct v4l2_subdev_pad_ops mt9m114_ifp_pad_ops = { @@ -1976,6 +1976,8 @@ static const struct v4l2_subdev_pad_ops mt9m114_ifp_pad_ops = { .set_fmt = mt9m114_ifp_set_fmt, .get_selection = mt9m114_ifp_get_selection, .set_selection = mt9m114_ifp_set_selection, + .get_frame_interval = mt9m114_ifp_get_frame_interval, + .set_frame_interval = mt9m114_ifp_set_frame_interval, }; static const struct v4l2_subdev_ops mt9m114_ifp_ops = { diff --git a/drivers/media/i2c/mt9v011.c b/drivers/media/i2c/mt9v011.c index 7f313d731839..10229bcb034b 100644 --- a/drivers/media/i2c/mt9v011.c +++ b/drivers/media/i2c/mt9v011.c @@ -362,8 +362,9 @@ static int mt9v011_set_fmt(struct v4l2_subdev *sd, return 0; } -static int mt9v011_g_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *ival) +static int mt9v011_get_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *ival) { calc_fps(sd, &ival->interval.numerator, @@ -372,8 +373,9 @@ static int mt9v011_g_frame_interval(struct v4l2_subdev *sd, return 0; } -static int mt9v011_s_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *ival) +static int mt9v011_set_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *ival) { struct v4l2_fract *tpf = &ival->interval; u16 speed; @@ -455,19 +457,15 @@ static const struct v4l2_subdev_core_ops mt9v011_core_ops = { #endif }; -static const struct v4l2_subdev_video_ops mt9v011_video_ops = { - .g_frame_interval = mt9v011_g_frame_interval, - .s_frame_interval = mt9v011_s_frame_interval, -}; - static const struct v4l2_subdev_pad_ops mt9v011_pad_ops = { .enum_mbus_code = mt9v011_enum_mbus_code, .set_fmt = mt9v011_set_fmt, + .get_frame_interval = mt9v011_get_frame_interval, + .set_frame_interval = mt9v011_set_frame_interval, }; static const struct v4l2_subdev_ops mt9v011_ops = { .core = &mt9v011_core_ops, - .video = &mt9v011_video_ops, .pad = &mt9v011_pad_ops, }; diff --git a/drivers/media/i2c/mt9v111.c b/drivers/media/i2c/mt9v111.c index 2c321e4884be..9dde019fc883 100644 --- a/drivers/media/i2c/mt9v111.c +++ b/drivers/media/i2c/mt9v111.c @@ -35,7 +35,7 @@ * The IFP can produce several output image formats from the sensor core * output. This driver currently supports only YUYV format permutations. * - * The driver allows manual frame rate control through s_frame_interval subdev + * The driver allows manual frame rate control through set_frame_interval subdev * operation or V4L2_CID_V/HBLANK controls, but it is known that the * auto-exposure algorithm might modify the programmed frame rate. While the * driver initially programs the sensor with auto-exposure and @@ -719,8 +719,9 @@ static int mt9v111_s_stream(struct v4l2_subdev *subdev, int enable) return ret; } -static int mt9v111_s_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *ival) +static int mt9v111_set_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *ival) { struct mt9v111_dev *mt9v111 = sd_to_mt9v111(sd); struct v4l2_fract *tpf = &ival->interval; @@ -771,8 +772,9 @@ static int mt9v111_s_frame_interval(struct v4l2_subdev *sd, return 0; } -static int mt9v111_g_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *ival) +static int mt9v111_get_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *ival) { struct mt9v111_dev *mt9v111 = sd_to_mt9v111(sd); struct v4l2_fract *tpf = &ival->interval; @@ -962,8 +964,6 @@ static const struct v4l2_subdev_core_ops mt9v111_core_ops = { static const struct v4l2_subdev_video_ops mt9v111_video_ops = { .s_stream = mt9v111_s_stream, - .s_frame_interval = mt9v111_s_frame_interval, - .g_frame_interval = mt9v111_g_frame_interval, }; static const struct v4l2_subdev_pad_ops mt9v111_pad_ops = { @@ -973,6 +973,8 @@ static const struct v4l2_subdev_pad_ops mt9v111_pad_ops = { .enum_frame_interval = mt9v111_enum_frame_interval, .get_fmt = mt9v111_get_format, .set_fmt = mt9v111_set_format, + .get_frame_interval = mt9v111_get_frame_interval, + .set_frame_interval = mt9v111_set_frame_interval, }; static const struct v4l2_subdev_ops mt9v111_ops = { diff --git a/drivers/media/i2c/ov2680.c b/drivers/media/i2c/ov2680.c index f58fa2eb86ee..e1024e23c9cb 100644 --- a/drivers/media/i2c/ov2680.c +++ b/drivers/media/i2c/ov2680.c @@ -552,7 +552,8 @@ static int ov2680_power_on(struct ov2680_dev *sensor) return ret; } -static int ov2680_s_g_frame_interval(struct v4l2_subdev *sd, +static int ov2680_get_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, struct v4l2_subdev_frame_interval *fi) { struct ov2680_dev *sensor = to_ov2680_dev(sd); @@ -870,8 +871,6 @@ static const struct v4l2_ctrl_ops ov2680_ctrl_ops = { }; static const struct v4l2_subdev_video_ops ov2680_video_ops = { - .g_frame_interval = ov2680_s_g_frame_interval, - .s_frame_interval = ov2680_s_g_frame_interval, .s_stream = ov2680_s_stream, }; @@ -884,6 +883,8 @@ static const struct v4l2_subdev_pad_ops ov2680_pad_ops = { .set_fmt = ov2680_set_fmt, .get_selection = ov2680_get_selection, .set_selection = ov2680_set_selection, + .get_frame_interval = ov2680_get_frame_interval, + .set_frame_interval = ov2680_get_frame_interval, }; static const struct v4l2_subdev_ops ov2680_subdev_ops = { diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c index 40532f7bcabe..6e7c19a2af82 100644 --- a/drivers/media/i2c/ov5640.c +++ b/drivers/media/i2c/ov5640.c @@ -399,7 +399,7 @@ struct ov5640_mode_info { const struct reg_value *reg_data; u32 reg_data_size; - /* Used by s_frame_interval only. */ + /* Used by set_frame_interval only. */ u32 max_fps; u32 def_fps; }; @@ -3605,8 +3605,9 @@ static int ov5640_enum_frame_interval( return 0; } -static int ov5640_g_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *fi) +static int ov5640_get_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *fi) { struct ov5640_dev *sensor = to_ov5640_dev(sd); @@ -3617,8 +3618,9 @@ static int ov5640_g_frame_interval(struct v4l2_subdev *sd, return 0; } -static int ov5640_s_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *fi) +static int ov5640_set_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *fi) { struct ov5640_dev *sensor = to_ov5640_dev(sd); const struct ov5640_mode_info *mode; @@ -3771,8 +3773,6 @@ static const struct v4l2_subdev_core_ops ov5640_core_ops = { }; static const struct v4l2_subdev_video_ops ov5640_video_ops = { - .g_frame_interval = ov5640_g_frame_interval, - .s_frame_interval = ov5640_s_frame_interval, .s_stream = ov5640_s_stream, }; @@ -3782,6 +3782,8 @@ static const struct v4l2_subdev_pad_ops ov5640_pad_ops = { .get_fmt = ov5640_get_fmt, .set_fmt = ov5640_set_fmt, .get_selection = ov5640_get_selection, + .get_frame_interval = ov5640_get_frame_interval, + .set_frame_interval = ov5640_set_frame_interval, .enum_frame_size = ov5640_enum_frame_size, .enum_frame_interval = ov5640_enum_frame_interval, }; diff --git a/drivers/media/i2c/ov5648.c b/drivers/media/i2c/ov5648.c index aa10eb4e3991..3c81953591d8 100644 --- a/drivers/media/i2c/ov5648.c +++ b/drivers/media/i2c/ov5648.c @@ -2158,37 +2158,8 @@ static int ov5648_s_stream(struct v4l2_subdev *subdev, int enable) return 0; } -static int ov5648_g_frame_interval(struct v4l2_subdev *subdev, - struct v4l2_subdev_frame_interval *interval) -{ - struct ov5648_sensor *sensor = ov5648_subdev_sensor(subdev); - const struct ov5648_mode *mode; - int ret = 0; - - mutex_lock(&sensor->mutex); - - mode = sensor->state.mode; - - switch (sensor->state.mbus_code) { - case MEDIA_BUS_FMT_SBGGR8_1X8: - interval->interval = mode->frame_interval[0]; - break; - case MEDIA_BUS_FMT_SBGGR10_1X10: - interval->interval = mode->frame_interval[1]; - break; - default: - ret = -EINVAL; - } - - mutex_unlock(&sensor->mutex); - - return ret; -} - static const struct v4l2_subdev_video_ops ov5648_subdev_video_ops = { .s_stream = ov5648_s_stream, - .g_frame_interval = ov5648_g_frame_interval, - .s_frame_interval = ov5648_g_frame_interval, }; /* Subdev Pad Operations */ @@ -2297,6 +2268,34 @@ static int ov5648_set_fmt(struct v4l2_subdev *subdev, return ret; } +static int ov5648_get_frame_interval(struct v4l2_subdev *subdev, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *interval) +{ + struct ov5648_sensor *sensor = ov5648_subdev_sensor(subdev); + const struct ov5648_mode *mode; + int ret = 0; + + mutex_lock(&sensor->mutex); + + mode = sensor->state.mode; + + switch (sensor->state.mbus_code) { + case MEDIA_BUS_FMT_SBGGR8_1X8: + interval->interval = mode->frame_interval[0]; + break; + case MEDIA_BUS_FMT_SBGGR10_1X10: + interval->interval = mode->frame_interval[1]; + break; + default: + ret = -EINVAL; + } + + mutex_unlock(&sensor->mutex); + + return ret; +} + static int ov5648_enum_frame_size(struct v4l2_subdev *subdev, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_frame_size_enum *size_enum) @@ -2363,6 +2362,8 @@ static const struct v4l2_subdev_pad_ops ov5648_subdev_pad_ops = { .enum_mbus_code = ov5648_enum_mbus_code, .get_fmt = ov5648_get_fmt, .set_fmt = ov5648_set_fmt, + .get_frame_interval = ov5648_get_frame_interval, + .set_frame_interval = ov5648_get_frame_interval, .enum_frame_size = ov5648_enum_frame_size, .enum_frame_interval = ov5648_enum_frame_interval, }; diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c index 819425e21349..bff2f3fb9558 100644 --- a/drivers/media/i2c/ov5693.c +++ b/drivers/media/i2c/ov5693.c @@ -1004,8 +1004,9 @@ static int ov5693_s_stream(struct v4l2_subdev *sd, int enable) return ret; } -static int ov5693_g_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *interval) +static int ov5693_get_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *interval) { struct ov5693_device *ov5693 = to_ov5693_sensor(sd); unsigned int framesize = OV5693_FIXED_PPL * (ov5693->mode.format.height + @@ -1054,7 +1055,6 @@ static int ov5693_enum_frame_size(struct v4l2_subdev *sd, static const struct v4l2_subdev_video_ops ov5693_video_ops = { .s_stream = ov5693_s_stream, - .g_frame_interval = ov5693_g_frame_interval, }; static const struct v4l2_subdev_pad_ops ov5693_pad_ops = { @@ -1064,6 +1064,7 @@ static const struct v4l2_subdev_pad_ops ov5693_pad_ops = { .set_fmt = ov5693_set_fmt, .get_selection = ov5693_get_selection, .set_selection = ov5693_set_selection, + .get_frame_interval = ov5693_get_frame_interval, }; static const struct v4l2_subdev_ops ov5693_ops = { diff --git a/drivers/media/i2c/ov6650.c b/drivers/media/i2c/ov6650.c index 38d21b40f5d8..abf9e0467659 100644 --- a/drivers/media/i2c/ov6650.c +++ b/drivers/media/i2c/ov6650.c @@ -197,7 +197,7 @@ struct ov6650 { struct clk *clk; bool half_scale; /* scale down output by 2 */ struct v4l2_rect rect; /* sensor cropping window */ - struct v4l2_fract tpf; /* as requested with s_frame_interval */ + struct v4l2_fract tpf; /* as requested with set_frame_interval */ u32 code; }; @@ -799,8 +799,9 @@ static int ov6650_enum_frame_interval(struct v4l2_subdev *sd, return 0; } -static int ov6650_g_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *ival) +static int ov6650_get_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *ival) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct ov6650 *priv = to_ov6650(client); @@ -813,8 +814,9 @@ static int ov6650_g_frame_interval(struct v4l2_subdev *sd, return 0; } -static int ov6650_s_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *ival) +static int ov6650_set_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *ival) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct ov6650 *priv = to_ov6650(client); @@ -1006,8 +1008,6 @@ static int ov6650_get_mbus_config(struct v4l2_subdev *sd, static const struct v4l2_subdev_video_ops ov6650_video_ops = { .s_stream = ov6650_s_stream, - .g_frame_interval = ov6650_g_frame_interval, - .s_frame_interval = ov6650_s_frame_interval, }; static const struct v4l2_subdev_pad_ops ov6650_pad_ops = { @@ -1017,6 +1017,8 @@ static const struct v4l2_subdev_pad_ops ov6650_pad_ops = { .set_selection = ov6650_set_selection, .get_fmt = ov6650_get_fmt, .set_fmt = ov6650_set_fmt, + .get_frame_interval = ov6650_get_frame_interval, + .set_frame_interval = ov6650_set_frame_interval, .get_mbus_config = ov6650_get_mbus_config, }; diff --git a/drivers/media/i2c/ov7251.c b/drivers/media/i2c/ov7251.c index 6582cc0e2384..d96cc26b918d 100644 --- a/drivers/media/i2c/ov7251.c +++ b/drivers/media/i2c/ov7251.c @@ -1386,6 +1386,7 @@ static int ov7251_s_stream(struct v4l2_subdev *subdev, int enable) } static int ov7251_get_frame_interval(struct v4l2_subdev *subdev, + struct v4l2_subdev_state *sd_state, struct v4l2_subdev_frame_interval *fi) { struct ov7251 *ov7251 = to_ov7251(subdev); @@ -1398,6 +1399,7 @@ static int ov7251_get_frame_interval(struct v4l2_subdev *subdev, } static int ov7251_set_frame_interval(struct v4l2_subdev *subdev, + struct v4l2_subdev_state *sd_state, struct v4l2_subdev_frame_interval *fi) { struct ov7251 *ov7251 = to_ov7251(subdev); @@ -1436,8 +1438,6 @@ static int ov7251_set_frame_interval(struct v4l2_subdev *subdev, static const struct v4l2_subdev_video_ops ov7251_video_ops = { .s_stream = ov7251_s_stream, - .g_frame_interval = ov7251_get_frame_interval, - .s_frame_interval = ov7251_set_frame_interval, }; static const struct v4l2_subdev_pad_ops ov7251_subdev_pad_ops = { @@ -1448,6 +1448,8 @@ static const struct v4l2_subdev_pad_ops ov7251_subdev_pad_ops = { .get_fmt = ov7251_get_format, .set_fmt = ov7251_set_format, .get_selection = ov7251_get_selection, + .get_frame_interval = ov7251_get_frame_interval, + .set_frame_interval = ov7251_set_frame_interval, }; static const struct v4l2_subdev_ops ov7251_subdev_ops = { diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c index 172483597c54..71175f918373 100644 --- a/drivers/media/i2c/ov7670.c +++ b/drivers/media/i2c/ov7670.c @@ -1155,8 +1155,9 @@ static int ov7670_get_fmt(struct v4l2_subdev *sd, * Implement G/S_PARM. There is a "high quality" mode we could try * to do someday; for now, we just do the frame rate tweak. */ -static int ov7670_g_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *ival) +static int ov7670_get_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *ival) { struct ov7670_info *info = to_state(sd); @@ -1166,8 +1167,9 @@ static int ov7670_g_frame_interval(struct v4l2_subdev *sd, return 0; } -static int ov7670_s_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *ival) +static int ov7670_set_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *ival) { struct v4l2_fract *tpf = &ival->interval; struct ov7670_info *info = to_state(sd); @@ -1729,22 +1731,18 @@ static const struct v4l2_subdev_core_ops ov7670_core_ops = { #endif }; -static const struct v4l2_subdev_video_ops ov7670_video_ops = { - .s_frame_interval = ov7670_s_frame_interval, - .g_frame_interval = ov7670_g_frame_interval, -}; - static const struct v4l2_subdev_pad_ops ov7670_pad_ops = { .enum_frame_interval = ov7670_enum_frame_interval, .enum_frame_size = ov7670_enum_frame_size, .enum_mbus_code = ov7670_enum_mbus_code, .get_fmt = ov7670_get_fmt, .set_fmt = ov7670_set_fmt, + .get_frame_interval = ov7670_get_frame_interval, + .set_frame_interval = ov7670_set_frame_interval, }; static const struct v4l2_subdev_ops ov7670_ops = { .core = &ov7670_core_ops, - .video = &ov7670_video_ops, .pad = &ov7670_pad_ops, }; diff --git a/drivers/media/i2c/ov772x.c b/drivers/media/i2c/ov772x.c index 1fbf72152956..59d3b8d006e4 100644 --- a/drivers/media/i2c/ov772x.c +++ b/drivers/media/i2c/ov772x.c @@ -717,8 +717,9 @@ static int ov772x_set_frame_rate(struct ov772x_priv *priv, return 0; } -static int ov772x_g_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *ival) +static int ov772x_get_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *ival) { struct ov772x_priv *priv = to_ov772x(sd); struct v4l2_fract *tpf = &ival->interval; @@ -729,8 +730,9 @@ static int ov772x_g_frame_interval(struct v4l2_subdev *sd, return 0; } -static int ov772x_s_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *ival) +static int ov772x_set_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *ival) { struct ov772x_priv *priv = to_ov772x(sd); struct v4l2_fract *tpf = &ival->interval; @@ -1349,8 +1351,6 @@ static int ov772x_enum_mbus_code(struct v4l2_subdev *sd, static const struct v4l2_subdev_video_ops ov772x_subdev_video_ops = { .s_stream = ov772x_s_stream, - .s_frame_interval = ov772x_s_frame_interval, - .g_frame_interval = ov772x_g_frame_interval, }; static const struct v4l2_subdev_pad_ops ov772x_subdev_pad_ops = { @@ -1359,6 +1359,8 @@ static const struct v4l2_subdev_pad_ops ov772x_subdev_pad_ops = { .get_selection = ov772x_get_selection, .get_fmt = ov772x_get_fmt, .set_fmt = ov772x_set_fmt, + .get_frame_interval = ov772x_get_frame_interval, + .set_frame_interval = ov772x_set_frame_interval, }; static const struct v4l2_subdev_ops ov772x_subdev_ops = { diff --git a/drivers/media/i2c/ov7740.c b/drivers/media/i2c/ov7740.c index 356a45e65b81..9ef89f459f7c 100644 --- a/drivers/media/i2c/ov7740.c +++ b/drivers/media/i2c/ov7740.c @@ -638,34 +638,8 @@ static int ov7740_set_stream(struct v4l2_subdev *sd, int enable) return ret; } -static int ov7740_g_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *ival) -{ - struct v4l2_fract *tpf = &ival->interval; - - - tpf->numerator = 1; - tpf->denominator = 60; - - return 0; -} - -static int ov7740_s_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *ival) -{ - struct v4l2_fract *tpf = &ival->interval; - - - tpf->numerator = 1; - tpf->denominator = 60; - - return 0; -} - static const struct v4l2_subdev_video_ops ov7740_subdev_video_ops = { .s_stream = ov7740_set_stream, - .s_frame_interval = ov7740_s_frame_interval, - .g_frame_interval = ov7740_g_frame_interval, }; static const struct reg_sequence ov7740_format_yuyv[] = { @@ -853,12 +827,26 @@ static int ov7740_get_fmt(struct v4l2_subdev *sd, return 0; } +static int ov7740_get_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *ival) +{ + struct v4l2_fract *tpf = &ival->interval; + + tpf->numerator = 1; + tpf->denominator = 60; + + return 0; +} + static const struct v4l2_subdev_pad_ops ov7740_subdev_pad_ops = { .enum_frame_interval = ov7740_enum_frame_interval, .enum_frame_size = ov7740_enum_frame_size, .enum_mbus_code = ov7740_enum_mbus_code, .get_fmt = ov7740_get_fmt, .set_fmt = ov7740_set_fmt, + .get_frame_interval = ov7740_get_frame_interval, + .set_frame_interval = ov7740_get_frame_interval, }; static const struct v4l2_subdev_ops ov7740_subdev_ops = { diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c index f2213c6158d3..0a9efa340771 100644 --- a/drivers/media/i2c/ov8865.c +++ b/drivers/media/i2c/ov8865.c @@ -2640,33 +2640,8 @@ static int ov8865_s_stream(struct v4l2_subdev *subdev, int enable) return 0; } -static int ov8865_g_frame_interval(struct v4l2_subdev *subdev, - struct v4l2_subdev_frame_interval *interval) -{ - struct ov8865_sensor *sensor = ov8865_subdev_sensor(subdev); - const struct ov8865_mode *mode; - unsigned int framesize; - unsigned int fps; - - mutex_lock(&sensor->mutex); - - mode = sensor->state.mode; - framesize = mode->hts * (mode->output_size_y + - sensor->ctrls.vblank->val); - fps = DIV_ROUND_CLOSEST(sensor->ctrls.pixel_rate->val, framesize); - - interval->interval.numerator = 1; - interval->interval.denominator = fps; - - mutex_unlock(&sensor->mutex); - - return 0; -} - static const struct v4l2_subdev_video_ops ov8865_subdev_video_ops = { .s_stream = ov8865_s_stream, - .g_frame_interval = ov8865_g_frame_interval, - .s_frame_interval = ov8865_g_frame_interval, }; /* Subdev Pad Operations */ @@ -2862,6 +2837,30 @@ static int ov8865_get_selection(struct v4l2_subdev *subdev, return 0; } +static int ov8865_get_frame_interval(struct v4l2_subdev *subdev, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *interval) +{ + struct ov8865_sensor *sensor = ov8865_subdev_sensor(subdev); + const struct ov8865_mode *mode; + unsigned int framesize; + unsigned int fps; + + mutex_lock(&sensor->mutex); + + mode = sensor->state.mode; + framesize = mode->hts * (mode->output_size_y + + sensor->ctrls.vblank->val); + fps = DIV_ROUND_CLOSEST(sensor->ctrls.pixel_rate->val, framesize); + + interval->interval.numerator = 1; + interval->interval.denominator = fps; + + mutex_unlock(&sensor->mutex); + + return 0; +} + static const struct v4l2_subdev_pad_ops ov8865_subdev_pad_ops = { .enum_mbus_code = ov8865_enum_mbus_code, .get_fmt = ov8865_get_fmt, @@ -2869,6 +2868,8 @@ static const struct v4l2_subdev_pad_ops ov8865_subdev_pad_ops = { .enum_frame_size = ov8865_enum_frame_size, .get_selection = ov8865_get_selection, .set_selection = ov8865_get_selection, + .get_frame_interval = ov8865_get_frame_interval, + .set_frame_interval = ov8865_get_frame_interval, }; static const struct v4l2_subdev_ops ov8865_subdev_ops = { diff --git a/drivers/media/i2c/ov9650.c b/drivers/media/i2c/ov9650.c index da1ab5135eaa..6b2de4220cf4 100644 --- a/drivers/media/i2c/ov9650.c +++ b/drivers/media/i2c/ov9650.c @@ -1101,8 +1101,9 @@ static int ov965x_enum_frame_sizes(struct v4l2_subdev *sd, return 0; } -static int ov965x_g_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *fi) +static int ov965x_get_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *fi) { struct ov965x *ov965x = to_ov965x(sd); @@ -1148,8 +1149,9 @@ static int __ov965x_set_frame_interval(struct ov965x *ov965x, return 0; } -static int ov965x_s_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *fi) +static int ov965x_set_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *fi) { struct ov965x *ov965x = to_ov965x(sd); int ret; @@ -1374,12 +1376,12 @@ static const struct v4l2_subdev_pad_ops ov965x_pad_ops = { .enum_frame_size = ov965x_enum_frame_sizes, .get_fmt = ov965x_get_fmt, .set_fmt = ov965x_set_fmt, + .get_frame_interval = ov965x_get_frame_interval, + .set_frame_interval = ov965x_set_frame_interval, }; static const struct v4l2_subdev_video_ops ov965x_video_ops = { .s_stream = ov965x_s_stream, - .g_frame_interval = ov965x_g_frame_interval, - .s_frame_interval = ov965x_s_frame_interval, }; diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c index ed5b10731a14..236f63ac803d 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c +++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c @@ -869,8 +869,9 @@ static void s5c73m3_try_format(struct s5c73m3 *state, s5c73m3_fill_mbus_fmt(&fmt->format, *fs, code); } -static int s5c73m3_oif_g_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *fi) +static int s5c73m3_oif_get_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *fi) { struct s5c73m3 *state = oif_sd_to_s5c73m3(sd); @@ -918,8 +919,9 @@ static int __s5c73m3_set_frame_interval(struct s5c73m3 *state, return 0; } -static int s5c73m3_oif_s_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *fi) +static int s5c73m3_oif_set_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *fi) { struct s5c73m3 *state = oif_sd_to_s5c73m3(sd); int ret; @@ -1500,6 +1502,8 @@ static const struct v4l2_subdev_pad_ops s5c73m3_oif_pad_ops = { .enum_frame_interval = s5c73m3_oif_enum_frame_interval, .get_fmt = s5c73m3_oif_get_fmt, .set_fmt = s5c73m3_oif_set_fmt, + .get_frame_interval = s5c73m3_oif_get_frame_interval, + .set_frame_interval = s5c73m3_oif_set_frame_interval, .get_frame_desc = s5c73m3_oif_get_frame_desc, .set_frame_desc = s5c73m3_oif_set_frame_desc, }; @@ -1511,8 +1515,6 @@ static const struct v4l2_subdev_core_ops s5c73m3_oif_core_ops = { static const struct v4l2_subdev_video_ops s5c73m3_oif_video_ops = { .s_stream = s5c73m3_oif_s_stream, - .g_frame_interval = s5c73m3_oif_g_frame_interval, - .s_frame_interval = s5c73m3_oif_s_frame_interval, }; static const struct v4l2_subdev_ops oif_subdev_ops = { diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c index 67da2045f543..987d138fe022 100644 --- a/drivers/media/i2c/s5k5baf.c +++ b/drivers/media/i2c/s5k5baf.c @@ -1118,8 +1118,9 @@ static int s5k5baf_s_stream(struct v4l2_subdev *sd, int on) return ret; } -static int s5k5baf_g_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *fi) +static int s5k5baf_get_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *fi) { struct s5k5baf *state = to_s5k5baf(sd); @@ -1131,8 +1132,8 @@ static int s5k5baf_g_frame_interval(struct v4l2_subdev *sd, return 0; } -static void s5k5baf_set_frame_interval(struct s5k5baf *state, - struct v4l2_subdev_frame_interval *fi) +static void __s5k5baf_set_frame_interval(struct s5k5baf *state, + struct v4l2_subdev_frame_interval *fi) { struct v4l2_fract *i = &fi->interval; @@ -1155,13 +1156,14 @@ static void s5k5baf_set_frame_interval(struct s5k5baf *state, state->fiv); } -static int s5k5baf_s_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *fi) +static int s5k5baf_set_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *fi) { struct s5k5baf *state = to_s5k5baf(sd); mutex_lock(&state->lock); - s5k5baf_set_frame_interval(state, fi); + __s5k5baf_set_frame_interval(state, fi); mutex_unlock(&state->lock); return 0; } @@ -1529,11 +1531,11 @@ static const struct v4l2_subdev_pad_ops s5k5baf_pad_ops = { .set_fmt = s5k5baf_set_fmt, .get_selection = s5k5baf_get_selection, .set_selection = s5k5baf_set_selection, + .get_frame_interval = s5k5baf_get_frame_interval, + .set_frame_interval = s5k5baf_set_frame_interval, }; static const struct v4l2_subdev_video_ops s5k5baf_video_ops = { - .g_frame_interval = s5k5baf_g_frame_interval, - .s_frame_interval = s5k5baf_s_frame_interval, .s_stream = s5k5baf_s_stream, }; diff --git a/drivers/media/i2c/tvp514x.c b/drivers/media/i2c/tvp514x.c index c37f605cb75f..dee0cf992379 100644 --- a/drivers/media/i2c/tvp514x.c +++ b/drivers/media/i2c/tvp514x.c @@ -738,16 +738,10 @@ static int tvp514x_s_ctrl(struct v4l2_ctrl *ctrl) return err; } -/** - * tvp514x_g_frame_interval() - V4L2 decoder interface handler - * @sd: pointer to standard V4L2 sub-device structure - * @ival: pointer to a v4l2_subdev_frame_interval structure - * - * Returns the decoder's video CAPTURE parameters. - */ static int -tvp514x_g_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *ival) +tvp514x_get_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *ival) { struct tvp514x_decoder *decoder = to_decoder(sd); enum tvp514x_std current_std; @@ -762,17 +756,10 @@ tvp514x_g_frame_interval(struct v4l2_subdev *sd, return 0; } -/** - * tvp514x_s_frame_interval() - V4L2 decoder interface handler - * @sd: pointer to standard V4L2 sub-device structure - * @ival: pointer to a v4l2_subdev_frame_interval structure - * - * Configures the decoder to use the input parameters, if possible. If - * not possible, returns the appropriate error code. - */ static int -tvp514x_s_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *ival) +tvp514x_set_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *ival) { struct tvp514x_decoder *decoder = to_decoder(sd); struct v4l2_fract *timeperframe; @@ -940,8 +927,6 @@ static const struct v4l2_subdev_video_ops tvp514x_video_ops = { .s_std = tvp514x_s_std, .s_routing = tvp514x_s_routing, .querystd = tvp514x_querystd, - .g_frame_interval = tvp514x_g_frame_interval, - .s_frame_interval = tvp514x_s_frame_interval, .s_stream = tvp514x_s_stream, }; @@ -949,6 +934,8 @@ static const struct v4l2_subdev_pad_ops tvp514x_pad_ops = { .enum_mbus_code = tvp514x_enum_mbus_code, .get_fmt = tvp514x_get_pad_format, .set_fmt = tvp514x_set_pad_format, + .get_frame_interval = tvp514x_get_frame_interval, + .set_frame_interval = tvp514x_set_frame_interval, }; static const struct v4l2_subdev_ops tvp514x_ops = { diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index 25e0620deff1..4aef584e21da 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -1607,7 +1607,8 @@ static int vidioc_g_parm(struct file *file, void *priv, p->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; if (dev->is_webcam) { rc = v4l2_device_call_until_err(&v4l2->v4l2_dev, 0, - video, g_frame_interval, &ival); + pad, get_frame_interval, NULL, + &ival); if (!rc) p->parm.capture.timeperframe = ival.interval; } else { @@ -1639,7 +1640,8 @@ static int vidioc_s_parm(struct file *file, void *priv, p->parm.capture.readbuffers = EM28XX_MIN_BUF; p->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; rc = v4l2_device_call_until_err(&dev->v4l2->v4l2_dev, 0, - video, s_frame_interval, &ival); + pad, set_frame_interval, NULL, + &ival); if (!rc) p->parm.capture.timeperframe = ival.interval; return rc; diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c index 3a4b15a98e02..2c89ffead94c 100644 --- a/drivers/media/v4l2-core/v4l2-common.c +++ b/drivers/media/v4l2-core/v4l2-common.c @@ -195,9 +195,9 @@ int v4l2_g_parm_cap(struct video_device *vdev, if (vdev->device_caps & V4L2_CAP_READWRITE) a->parm.capture.readbuffers = 2; - if (v4l2_subdev_has_op(sd, video, g_frame_interval)) + if (v4l2_subdev_has_op(sd, pad, get_frame_interval)) a->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; - ret = v4l2_subdev_call(sd, video, g_frame_interval, &ival); + ret = v4l2_subdev_call_state_active(sd, pad, get_frame_interval, &ival); if (!ret) a->parm.capture.timeperframe = ival.interval; return ret; @@ -222,9 +222,9 @@ int v4l2_s_parm_cap(struct video_device *vdev, else a->parm.capture.readbuffers = 0; - if (v4l2_subdev_has_op(sd, video, g_frame_interval)) + if (v4l2_subdev_has_op(sd, pad, get_frame_interval)) a->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; - ret = v4l2_subdev_call(sd, video, s_frame_interval, &ival); + ret = v4l2_subdev_call_state_active(sd, pad, set_frame_interval, &ival); if (!ret) a->parm.capture.timeperframe = ival.interval; return ret; diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index be86b906c985..4104445c546e 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -245,29 +245,6 @@ static int call_enum_frame_size(struct v4l2_subdev *sd, sd->ops->pad->enum_frame_size(sd, state, fse); } -static inline int check_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *fi) -{ - if (!fi) - return -EINVAL; - - return check_pad(sd, fi->pad); -} - -static int call_g_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *fi) -{ - return check_frame_interval(sd, fi) ? : - sd->ops->video->g_frame_interval(sd, fi); -} - -static int call_s_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *fi) -{ - return check_frame_interval(sd, fi) ? : - sd->ops->video->s_frame_interval(sd, fi); -} - static int call_enum_frame_interval(struct v4l2_subdev *sd, struct v4l2_subdev_state *state, struct v4l2_subdev_frame_interval_enum *fie) @@ -307,6 +284,34 @@ static int call_set_selection(struct v4l2_subdev *sd, sd->ops->pad->set_selection(sd, state, sel); } +static inline int check_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_frame_interval *fi) +{ + if (!fi) + return -EINVAL; + + return check_pad(sd, fi->pad) ? : + check_state(sd, state, V4L2_SUBDEV_FORMAT_ACTIVE, fi->pad, + fi->stream); +} + +static int call_get_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_frame_interval *fi) +{ + return check_frame_interval(sd, state, fi) ? : + sd->ops->pad->get_frame_interval(sd, state, fi); +} + +static int call_set_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_frame_interval *fi) +{ + return check_frame_interval(sd, state, fi) ? : + sd->ops->pad->set_frame_interval(sd, state, fi); +} + static int call_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad, struct v4l2_mbus_frame_desc *fd) { @@ -479,6 +484,8 @@ static const struct v4l2_subdev_pad_ops v4l2_subdev_call_pad_wrappers = { .enum_frame_interval = call_enum_frame_interval_state, .get_selection = call_get_selection_state, .set_selection = call_set_selection_state, + .get_frame_interval = call_get_frame_interval, + .set_frame_interval = call_set_frame_interval, .get_edid = call_get_edid, .set_edid = call_set_edid, .dv_timings_cap = call_dv_timings_cap, @@ -488,8 +495,6 @@ static const struct v4l2_subdev_pad_ops v4l2_subdev_call_pad_wrappers = { }; static const struct v4l2_subdev_video_ops v4l2_subdev_call_video_wrappers = { - .g_frame_interval = call_g_frame_interval, - .s_frame_interval = call_s_frame_interval, .s_stream = call_s_stream, }; @@ -531,6 +536,10 @@ subdev_ioctl_get_state(struct v4l2_subdev *sd, struct v4l2_subdev_fh *subdev_fh, case VIDIOC_SUBDEV_S_SELECTION: 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; + break; case VIDIOC_SUBDEV_G_ROUTING: case VIDIOC_SUBDEV_S_ROUTING: which = ((struct v4l2_subdev_routing *)arg)->which; @@ -781,7 +790,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg, fi->stream = 0; memset(fi->reserved, 0, sizeof(fi->reserved)); - return v4l2_subdev_call(sd, video, g_frame_interval, arg); + return v4l2_subdev_call(sd, pad, get_frame_interval, state, fi); } case VIDIOC_SUBDEV_S_FRAME_INTERVAL: { @@ -794,7 +803,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg, fi->stream = 0; memset(fi->reserved, 0, sizeof(fi->reserved)); - return v4l2_subdev_call(sd, video, s_frame_interval, arg); + return v4l2_subdev_call(sd, pad, set_frame_interval, state, fi); } case VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL: { diff --git a/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c b/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c index 58cddf11c9ab..a6f66b483e02 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c @@ -496,8 +496,9 @@ static int gc0310_s_stream(struct v4l2_subdev *sd, int enable) return ret; } -static int gc0310_g_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *interval) +static int gc0310_get_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *interval) { interval->interval.numerator = 1; interval->interval.denominator = GC0310_FPS; @@ -545,7 +546,6 @@ static const struct v4l2_subdev_sensor_ops gc0310_sensor_ops = { static const struct v4l2_subdev_video_ops gc0310_video_ops = { .s_stream = gc0310_s_stream, - .g_frame_interval = gc0310_g_frame_interval, }; static const struct v4l2_subdev_pad_ops gc0310_pad_ops = { @@ -553,6 +553,7 @@ static const struct v4l2_subdev_pad_ops gc0310_pad_ops = { .enum_frame_size = gc0310_enum_frame_size, .get_fmt = gc0310_get_fmt, .set_fmt = gc0310_set_fmt, + .get_frame_interval = gc0310_get_frame_interval, }; static const struct v4l2_subdev_ops gc0310_ops = { diff --git a/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c b/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c index 5e438c5fd4a9..074f69e2b5e0 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c @@ -698,8 +698,9 @@ static int gc2235_s_config(struct v4l2_subdev *sd, return ret; } -static int gc2235_g_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *interval) +static int gc2235_get_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *interval) { struct gc2235_device *dev = to_gc2235_sensor(sd); @@ -754,7 +755,6 @@ static const struct v4l2_subdev_sensor_ops gc2235_sensor_ops = { static const struct v4l2_subdev_video_ops gc2235_video_ops = { .s_stream = gc2235_s_stream, - .g_frame_interval = gc2235_g_frame_interval, }; static const struct v4l2_subdev_core_ops gc2235_core_ops = { @@ -767,6 +767,7 @@ static const struct v4l2_subdev_pad_ops gc2235_pad_ops = { .enum_frame_size = gc2235_enum_frame_size, .get_fmt = gc2235_get_fmt, .set_fmt = gc2235_set_fmt, + .get_frame_interval = gc2235_get_frame_interval, }; static const struct v4l2_subdev_ops gc2235_ops = { diff --git a/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c b/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c index db76f52e1dc8..9f6404967e64 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c @@ -1388,8 +1388,9 @@ static int mt9m114_t_vflip(struct v4l2_subdev *sd, int value) return !!err; } -static int mt9m114_g_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *interval) +static int mt9m114_get_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *interval) { struct mt9m114_device *dev = to_mt9m114_sensor(sd); @@ -1479,7 +1480,6 @@ static int mt9m114_g_skip_frames(struct v4l2_subdev *sd, u32 *frames) static const struct v4l2_subdev_video_ops mt9m114_video_ops = { .s_stream = mt9m114_s_stream, - .g_frame_interval = mt9m114_g_frame_interval, }; static const struct v4l2_subdev_sensor_ops mt9m114_sensor_ops = { @@ -1498,6 +1498,7 @@ static const struct v4l2_subdev_pad_ops mt9m114_pad_ops = { .get_fmt = mt9m114_get_fmt, .set_fmt = mt9m114_set_fmt, .set_selection = mt9m114_s_exposure_selection, + .get_frame_interval = mt9m114_get_frame_interval, }; static const struct v4l2_subdev_ops mt9m114_ops = { diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c index ae70e04040dd..5128c8ea6aed 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c @@ -845,8 +845,9 @@ static int ov2722_s_config(struct v4l2_subdev *sd, return ret; } -static int ov2722_g_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *interval) +static int ov2722_get_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *interval) { struct ov2722_device *dev = to_ov2722_sensor(sd); @@ -901,7 +902,6 @@ static const struct v4l2_subdev_sensor_ops ov2722_sensor_ops = { static const struct v4l2_subdev_video_ops ov2722_video_ops = { .s_stream = ov2722_s_stream, - .g_frame_interval = ov2722_g_frame_interval, }; static const struct v4l2_subdev_core_ops ov2722_core_ops = { @@ -914,6 +914,7 @@ static const struct v4l2_subdev_pad_ops ov2722_pad_ops = { .enum_frame_size = ov2722_enum_frame_size, .get_fmt = ov2722_get_fmt, .set_fmt = ov2722_set_fmt, + .get_frame_interval = ov2722_get_frame_interval, }; static const struct v4l2_subdev_ops ov2722_ops = { diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index 759233a7ba50..f44e6412f4e3 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -105,8 +105,8 @@ static unsigned short atomisp_get_sensor_fps(struct atomisp_sub_device *asd) unsigned short fps = 0; int ret; - ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, - video, g_frame_interval, &fi); + ret = v4l2_subdev_call_state_active(isp->inputs[asd->input_curr].camera, + pad, get_frame_interval, &fi); if (!ret && fi.interval.numerator) fps = fi.interval.denominator / fi.interval.numerator; diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index a8e4779d007f..a9c2a2c71d4b 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -1739,8 +1739,8 @@ static int atomisp_s_parm(struct file *file, void *fh, fi.interval = parm->parm.capture.timeperframe; - rval = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, - video, s_frame_interval, &fi); + rval = v4l2_subdev_call_state_active(isp->inputs[asd->input_curr].camera, + pad, set_frame_interval, &fi); if (!rval) parm->parm.capture.timeperframe = fi.interval; diff --git a/drivers/staging/media/imx/imx-ic-prp.c b/drivers/staging/media/imx/imx-ic-prp.c index ac5fb332088e..6088a1aaa695 100644 --- a/drivers/staging/media/imx/imx-ic-prp.c +++ b/drivers/staging/media/imx/imx-ic-prp.c @@ -395,8 +395,9 @@ static int prp_s_stream(struct v4l2_subdev *sd, int enable) return ret; } -static int prp_g_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *fi) +static int prp_get_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *fi) { struct prp_priv *priv = sd_to_priv(sd); @@ -410,8 +411,9 @@ static int prp_g_frame_interval(struct v4l2_subdev *sd, return 0; } -static int prp_s_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *fi) +static int prp_set_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *fi) { struct prp_priv *priv = sd_to_priv(sd); @@ -454,12 +456,12 @@ static const struct v4l2_subdev_pad_ops prp_pad_ops = { .enum_mbus_code = prp_enum_mbus_code, .get_fmt = prp_get_fmt, .set_fmt = prp_set_fmt, + .get_frame_interval = prp_get_frame_interval, + .set_frame_interval = prp_set_frame_interval, .link_validate = prp_link_validate, }; static const struct v4l2_subdev_video_ops prp_video_ops = { - .g_frame_interval = prp_g_frame_interval, - .s_frame_interval = prp_s_frame_interval, .s_stream = prp_s_stream, }; diff --git a/drivers/staging/media/imx/imx-ic-prpencvf.c b/drivers/staging/media/imx/imx-ic-prpencvf.c index 9b81cfbcd777..50e748cd10df 100644 --- a/drivers/staging/media/imx/imx-ic-prpencvf.c +++ b/drivers/staging/media/imx/imx-ic-prpencvf.c @@ -1205,8 +1205,9 @@ static int prp_s_stream(struct v4l2_subdev *sd, int enable) return ret; } -static int prp_g_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *fi) +static int prp_get_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *fi) { struct prp_priv *priv = sd_to_priv(sd); @@ -1220,8 +1221,9 @@ static int prp_g_frame_interval(struct v4l2_subdev *sd, return 0; } -static int prp_s_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *fi) +static int prp_set_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *fi) { struct prp_priv *priv = sd_to_priv(sd); @@ -1303,11 +1305,11 @@ static const struct v4l2_subdev_pad_ops prp_pad_ops = { .enum_frame_size = prp_enum_frame_size, .get_fmt = prp_get_fmt, .set_fmt = prp_set_fmt, + .get_frame_interval = prp_get_frame_interval, + .set_frame_interval = prp_set_frame_interval, }; static const struct v4l2_subdev_video_ops prp_video_ops = { - .g_frame_interval = prp_g_frame_interval, - .s_frame_interval = prp_s_frame_interval, .s_stream = prp_s_stream, }; diff --git a/drivers/staging/media/imx/imx-media-capture.c b/drivers/staging/media/imx/imx-media-capture.c index 4846078315ff..0752c9a71efd 100644 --- a/drivers/staging/media/imx/imx-media-capture.c +++ b/drivers/staging/media/imx/imx-media-capture.c @@ -511,7 +511,8 @@ static int capture_legacy_g_parm(struct file *file, void *fh, if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - ret = v4l2_subdev_call(priv->src_sd, video, g_frame_interval, &fi); + ret = v4l2_subdev_call_state_active(priv->src_sd, pad, + get_frame_interval, &fi); if (ret < 0) return ret; @@ -534,7 +535,8 @@ static int capture_legacy_s_parm(struct file *file, void *fh, return -EINVAL; fi.interval = a->parm.capture.timeperframe; - ret = v4l2_subdev_call(priv->src_sd, video, s_frame_interval, &fi); + ret = v4l2_subdev_call_state_active(priv->src_sd, pad, + set_frame_interval, &fi); if (ret < 0) return ret; diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c index dda1ebc34692..96e351c9bf03 100644 --- a/drivers/staging/media/imx/imx-media-csi.c +++ b/drivers/staging/media/imx/imx-media-csi.c @@ -902,8 +902,9 @@ static const struct csi_skip_desc *csi_find_best_skip(struct v4l2_fract *in, * V4L2 subdev operations. */ -static int csi_g_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *fi) +static int csi_get_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *fi) { struct csi_priv *priv = v4l2_get_subdevdata(sd); @@ -919,8 +920,9 @@ static int csi_g_frame_interval(struct v4l2_subdev *sd, return 0; } -static int csi_s_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *fi) +static int csi_set_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *fi) { struct csi_priv *priv = v4l2_get_subdevdata(sd); struct v4l2_fract *input_fi; @@ -1862,8 +1864,6 @@ static const struct v4l2_subdev_core_ops csi_core_ops = { }; static const struct v4l2_subdev_video_ops csi_video_ops = { - .g_frame_interval = csi_g_frame_interval, - .s_frame_interval = csi_s_frame_interval, .s_stream = csi_s_stream, }; @@ -1876,6 +1876,8 @@ static const struct v4l2_subdev_pad_ops csi_pad_ops = { .set_fmt = csi_set_fmt, .get_selection = csi_get_selection, .set_selection = csi_set_selection, + .get_frame_interval = csi_get_frame_interval, + .set_frame_interval = csi_set_frame_interval, .link_validate = csi_link_validate, }; diff --git a/drivers/staging/media/imx/imx-media-vdic.c b/drivers/staging/media/imx/imx-media-vdic.c index 3c2093c520ba..3c5224a6b910 100644 --- a/drivers/staging/media/imx/imx-media-vdic.c +++ b/drivers/staging/media/imx/imx-media-vdic.c @@ -780,8 +780,9 @@ static int vdic_link_validate(struct v4l2_subdev *sd, return ret; } -static int vdic_g_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *fi) +static int vdic_get_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *fi) { struct vdic_priv *priv = v4l2_get_subdevdata(sd); @@ -797,8 +798,9 @@ static int vdic_g_frame_interval(struct v4l2_subdev *sd, return 0; } -static int vdic_s_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *fi) +static int vdic_set_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *fi) { struct vdic_priv *priv = v4l2_get_subdevdata(sd); struct v4l2_fract *input_fi, *output_fi; @@ -886,12 +888,12 @@ static const struct v4l2_subdev_pad_ops vdic_pad_ops = { .enum_mbus_code = vdic_enum_mbus_code, .get_fmt = vdic_get_fmt, .set_fmt = vdic_set_fmt, + .get_frame_interval = vdic_get_frame_interval, + .set_frame_interval = vdic_set_frame_interval, .link_validate = vdic_link_validate, }; static const struct v4l2_subdev_video_ops vdic_video_ops = { - .g_frame_interval = vdic_g_frame_interval, - .s_frame_interval = vdic_s_frame_interval, .s_stream = vdic_s_stream, }; diff --git a/drivers/staging/media/tegra-video/csi.c b/drivers/staging/media/tegra-video/csi.c index 9aa72863c213..7594ec6465f0 100644 --- a/drivers/staging/media/tegra-video/csi.c +++ b/drivers/staging/media/tegra-video/csi.c @@ -222,8 +222,9 @@ static int csi_set_format(struct v4l2_subdev *subdev, /* * V4L2 Subdevice Video Operations */ -static int tegra_csi_g_frame_interval(struct v4l2_subdev *subdev, - struct v4l2_subdev_frame_interval *vfi) +static int tegra_csi_get_frame_interval(struct v4l2_subdev *subdev, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *vfi) { struct tegra_csi_channel *csi_chan = to_csi_chan(subdev); @@ -430,8 +431,6 @@ static int tegra_csi_s_stream(struct v4l2_subdev *subdev, int enable) */ static const struct v4l2_subdev_video_ops tegra_csi_video_ops = { .s_stream = tegra_csi_s_stream, - .g_frame_interval = tegra_csi_g_frame_interval, - .s_frame_interval = tegra_csi_g_frame_interval, }; static const struct v4l2_subdev_pad_ops tegra_csi_pad_ops = { @@ -440,6 +439,8 @@ static const struct v4l2_subdev_pad_ops tegra_csi_pad_ops = { .enum_frame_interval = csi_enum_frameintervals, .get_fmt = csi_get_format, .set_fmt = csi_set_format, + .get_frame_interval = tegra_csi_get_frame_interval, + .set_frame_interval = tegra_csi_get_frame_interval, }; static const struct v4l2_subdev_ops tegra_csi_ops = { diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index d278836fd9cb..acf5be24a5ca 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -425,7 +425,7 @@ __v4l2_find_nearest_size(const void *array, size_t array_size, /** * v4l2_g_parm_cap - helper routine for vidioc_g_parm to fill this in by - * calling the g_frame_interval op of the given subdev. It only works + * calling the get_frame_interval op of the given subdev. It only works * for V4L2_BUF_TYPE_VIDEO_CAPTURE(_MPLANE), hence the _cap in the * function name. * @@ -438,7 +438,7 @@ int v4l2_g_parm_cap(struct video_device *vdev, /** * v4l2_s_parm_cap - helper routine for vidioc_s_parm to fill this in by - * calling the s_frame_interval op of the given subdev. It only works + * calling the set_frame_interval op of the given subdev. It only works * for V4L2_BUF_TYPE_VIDEO_CAPTURE(_MPLANE), hence the _cap in the * function name. * diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index bbcee4f3da1e..962b546d0e3b 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -452,12 +452,6 @@ enum v4l2_subdev_pre_streamon_flags { * * @g_pixelaspect: callback to return the pixelaspect ratio. * - * @g_frame_interval: callback for VIDIOC_SUBDEV_G_FRAME_INTERVAL() - * ioctl handler code. - * - * @s_frame_interval: callback for VIDIOC_SUBDEV_S_FRAME_INTERVAL() - * ioctl handler code. - * * @s_dv_timings: Set custom dv timings in the sub device. This is used * when sub device is capable of setting detailed timing information * in the hardware to generate/detect the video signal. @@ -496,10 +490,6 @@ struct v4l2_subdev_video_ops { int (*g_input_status)(struct v4l2_subdev *sd, u32 *status); int (*s_stream)(struct v4l2_subdev *sd, int enable); int (*g_pixelaspect)(struct v4l2_subdev *sd, struct v4l2_fract *aspect); - 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 (*s_dv_timings)(struct v4l2_subdev *sd, struct v4l2_dv_timings *timings); int (*g_dv_timings)(struct v4l2_subdev *sd, @@ -786,6 +776,12 @@ struct v4l2_subdev_state { * * @set_selection: callback for VIDIOC_SUBDEV_S_SELECTION() ioctl handler code. * + * @get_frame_interval: callback for VIDIOC_SUBDEV_G_FRAME_INTERVAL() + * ioctl handler code. + * + * @set_frame_interval: callback for VIDIOC_SUBDEV_S_FRAME_INTERVAL() + * ioctl handler code. + * * @get_edid: callback for VIDIOC_SUBDEV_G_EDID() ioctl handler code. * * @set_edid: callback for VIDIOC_SUBDEV_S_EDID() ioctl handler code. @@ -857,6 +853,12 @@ struct v4l2_subdev_pad_ops { int (*set_selection)(struct v4l2_subdev *sd, struct v4l2_subdev_state *state, struct v4l2_subdev_selection *sel); + int (*get_frame_interval)(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_frame_interval *interval); + int (*set_frame_interval)(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_frame_interval *interval); int (*get_edid)(struct v4l2_subdev *sd, struct v4l2_edid *edid); int (*set_edid)(struct v4l2_subdev *sd, struct v4l2_edid *edid); int (*dv_timings_cap)(struct v4l2_subdev *sd, From patchwork Tue Oct 24 00:51:28 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 13433793 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B1D26C25B67 for ; Tue, 24 Oct 2023 00:51:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231588AbjJXAvj (ORCPT ); Mon, 23 Oct 2023 20:51:39 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39508 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231706AbjJXAvc (ORCPT ); Mon, 23 Oct 2023 20:51:32 -0400 Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6B5A0C0 for ; Mon, 23 Oct 2023 17:51:27 -0700 (PDT) Received: from pendragon.ideasonboard.com (213-243-189-158.bb.dnainternet.fi [213.243.189.158]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id ACF82922; Tue, 24 Oct 2023 02:51:14 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1698108674; bh=y7vacwG4Kfaar6AZqcRURFnA4en2ZsmeAPZSvT44KP0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=mkuCpUJvLwHlNmXmwmrQURv+pfFnj1I6jF7i4y3IPtTJ4VjefDrSAVajQadz8/fd7 sSXV++9HRkRAUIeixBiuekLzHfyKHwq8TwIJS9IiUoSTujIbORmW1ZJ2aBrHUq7g4n B0ysTSYih/Ttlmk5Sq/SjdhlWb2YmBxPE8dluCEk= From: Laurent Pinchart To: linux-media@vger.kernel.org Cc: Sakari Ailus , Hans Verkuil , Tomi Valkeinen , Hans de Goede Subject: [RFC PATCH v1 2/4] media: v4l2-subdev: Add which field to struct v4l2_subdev_frame_interval Date: Tue, 24 Oct 2023 03:51:28 +0300 Message-ID: <20231024005130.28026-3-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20231024005130.28026-1-laurent.pinchart@ideasonboard.com> References: <20231024005130.28026-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org 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. Add 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_WHICH_INTERVAL, to indicate that userspace is aware of this new field. All drivers that implement the subdev .g_frame_interval() and .s_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 --- .../media/v4l/vidioc-subdev-g-client-cap.rst | 5 +++++ .../v4l/vidioc-subdev-g-frame-interval.rst | 17 +++++++++------ drivers/media/i2c/adv7180.c | 3 +++ drivers/media/i2c/et8ek8/et8ek8_driver.c | 6 ++++++ drivers/media/i2c/imx214.c | 3 +++ drivers/media/i2c/imx274.c | 6 ++++++ drivers/media/i2c/max9286.c | 6 ++++++ drivers/media/i2c/mt9m111.c | 6 ++++++ drivers/media/i2c/mt9m114.c | 6 ++++++ drivers/media/i2c/mt9v011.c | 6 ++++++ drivers/media/i2c/mt9v111.c | 6 ++++++ drivers/media/i2c/ov2680.c | 3 +++ drivers/media/i2c/ov5640.c | 6 ++++++ drivers/media/i2c/ov5648.c | 3 +++ drivers/media/i2c/ov5693.c | 3 +++ drivers/media/i2c/ov6650.c | 6 ++++++ drivers/media/i2c/ov7251.c | 6 ++++++ drivers/media/i2c/ov7670.c | 4 ++++ drivers/media/i2c/ov772x.c | 6 ++++++ drivers/media/i2c/ov8865.c | 3 +++ drivers/media/i2c/ov9650.c | 6 ++++++ drivers/media/i2c/s5c73m3/s5c73m3-core.c | 6 ++++++ drivers/media/i2c/s5k5baf.c | 6 ++++++ drivers/media/i2c/tvp514x.c | 4 ++++ drivers/media/v4l2-core/v4l2-subdev.c | 21 ++++++++++++------- .../media/atomisp/i2c/atomisp-gc0310.c | 3 +++ .../media/atomisp/i2c/atomisp-gc2235.c | 3 +++ .../media/atomisp/i2c/atomisp-mt9m114.c | 3 +++ .../media/atomisp/i2c/atomisp-ov2722.c | 3 +++ drivers/staging/media/imx/imx-ic-prp.c | 6 ++++++ drivers/staging/media/imx/imx-ic-prpencvf.c | 6 ++++++ drivers/staging/media/imx/imx-media-csi.c | 6 ++++++ drivers/staging/media/imx/imx-media-vdic.c | 6 ++++++ drivers/staging/media/tegra-video/csi.c | 3 +++ include/uapi/linux/v4l2-subdev.h | 13 ++++++++++-- 35 files changed, 190 insertions(+), 15 deletions(-) diff --git a/Documentation/userspace-api/media/v4l/vidioc-subdev-g-client-cap.rst b/Documentation/userspace-api/media/v4l/vidioc-subdev-g-client-cap.rst index 20f12a1cc0f7..f168140ebd59 100644 --- a/Documentation/userspace-api/media/v4l/vidioc-subdev-g-client-cap.rst +++ b/Documentation/userspace-api/media/v4l/vidioc-subdev-g-client-cap.rst @@ -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_WHICH_INTERVAL`` + - 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 ============ diff --git a/Documentation/userspace-api/media/v4l/vidioc-subdev-g-frame-interval.rst b/Documentation/userspace-api/media/v4l/vidioc-subdev-g-frame-interval.rst index 842f962d2aea..41e0e2c8ecc3 100644 --- a/Documentation/userspace-api/media/v4l/vidioc-subdev-g-frame-interval.rst +++ b/Documentation/userspace-api/media/v4l/vidioc-subdev-g-frame-interval.rst @@ -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 `. + * - __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``. diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index 1bd8d9bbb82c..8bb8838eb566 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c @@ -469,6 +469,9 @@ static int adv7180_get_frame_interval(struct v4l2_subdev *sd, { struct adv7180_state *state = to_state(sd); + 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; diff --git a/drivers/media/i2c/et8ek8/et8ek8_driver.c b/drivers/media/i2c/et8ek8/et8ek8_driver.c index 949859aff1ec..240863b75491 100644 --- a/drivers/media/i2c/et8ek8/et8ek8_driver.c +++ b/drivers/media/i2c/et8ek8/et8ek8_driver.c @@ -1052,6 +1052,9 @@ static int et8ek8_get_frame_interval(struct v4l2_subdev *subdev, { struct et8ek8_sensor *sensor = to_et8ek8_sensor(subdev); + if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + memset(fi, 0, sizeof(*fi)); fi->interval = sensor->current_reglist->mode.timeperframe; @@ -1065,6 +1068,9 @@ static int et8ek8_set_frame_interval(struct v4l2_subdev *subdev, struct et8ek8_sensor *sensor = to_et8ek8_sensor(subdev); struct et8ek8_reglist *reglist; + if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + reglist = et8ek8_reglist_find_mode_ival(&meta_reglist, sensor->current_reglist, &fi->interval); diff --git a/drivers/media/i2c/imx214.c b/drivers/media/i2c/imx214.c index c84de2700c0c..fbf3fcf5d61d 100644 --- a/drivers/media/i2c/imx214.c +++ b/drivers/media/i2c/imx214.c @@ -799,6 +799,9 @@ static int imx214_get_frame_interval(struct v4l2_subdev *subdev, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_frame_interval *fival) { + if (fival->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + fival->interval.numerator = 1; fival->interval.denominator = IMX214_FPS; diff --git a/drivers/media/i2c/imx274.c b/drivers/media/i2c/imx274.c index 444a5a6d22cd..5ffddabc22a9 100644 --- a/drivers/media/i2c/imx274.c +++ b/drivers/media/i2c/imx274.c @@ -1333,6 +1333,9 @@ static int imx274_get_frame_interval(struct v4l2_subdev *sd, { struct stimx274 *imx274 = to_imx274(sd); + 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 +1353,9 @@ static int imx274_set_frame_interval(struct v4l2_subdev *sd, int min, max, def; int ret; + if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + ret = pm_runtime_resume_and_get(&imx274->client->dev); if (ret < 0) return ret; diff --git a/drivers/media/i2c/max9286.c b/drivers/media/i2c/max9286.c index ccf615a12b4f..a16c19bef879 100644 --- a/drivers/media/i2c/max9286.c +++ b/drivers/media/i2c/max9286.c @@ -874,6 +874,9 @@ static int max9286_get_frame_interval(struct v4l2_subdev *sd, { struct max9286_priv *priv = sd_to_max9286(sd); + if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + if (interval->pad != MAX9286_SRC_PAD) return -EINVAL; @@ -888,6 +891,9 @@ static int max9286_set_frame_interval(struct v4l2_subdev *sd, { struct max9286_priv *priv = sd_to_max9286(sd); + if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + if (interval->pad != MAX9286_SRC_PAD) return -EINVAL; diff --git a/drivers/media/i2c/mt9m111.c b/drivers/media/i2c/mt9m111.c index c96ad4f58a88..d853aa631327 100644 --- a/drivers/media/i2c/mt9m111.c +++ b/drivers/media/i2c/mt9m111.c @@ -1051,6 +1051,9 @@ static int mt9m111_get_frame_interval(struct v4l2_subdev *sd, { struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev); + if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + fi->interval = mt9m111->frame_interval; return 0; @@ -1068,6 +1071,9 @@ static int mt9m111_set_frame_interval(struct v4l2_subdev *sd, if (mt9m111->is_streaming) return -EBUSY; + if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + if (fi->pad != 0) return -EINVAL; diff --git a/drivers/media/i2c/mt9m114.c b/drivers/media/i2c/mt9m114.c index c48e6e0e9292..19551c400dbd 100644 --- a/drivers/media/i2c/mt9m114.c +++ b/drivers/media/i2c/mt9m114.c @@ -1588,6 +1588,9 @@ static int mt9m114_ifp_get_frame_interval(struct v4l2_subdev *sd, struct v4l2_fract *ival = &interval->interval; struct mt9m114 *sensor = ifp_to_mt9m114(sd); + if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + mutex_lock(sensor->ifp.hdl.lock); ival->numerator = 1; @@ -1606,6 +1609,9 @@ static int mt9m114_ifp_set_frame_interval(struct v4l2_subdev *sd, struct mt9m114 *sensor = ifp_to_mt9m114(sd); int ret = 0; + if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + mutex_lock(sensor->ifp.hdl.lock); if (ival->numerator != 0 && ival->denominator != 0) diff --git a/drivers/media/i2c/mt9v011.c b/drivers/media/i2c/mt9v011.c index 10229bcb034b..7a1bb836b092 100644 --- a/drivers/media/i2c/mt9v011.c +++ b/drivers/media/i2c/mt9v011.c @@ -366,6 +366,9 @@ static int mt9v011_get_frame_interval(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_frame_interval *ival) { + if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + calc_fps(sd, &ival->interval.numerator, &ival->interval.denominator); @@ -380,6 +383,9 @@ static int mt9v011_set_frame_interval(struct v4l2_subdev *sd, struct v4l2_fract *tpf = &ival->interval; u16 speed; + 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); diff --git a/drivers/media/i2c/mt9v111.c b/drivers/media/i2c/mt9v111.c index 9dde019fc883..40c4f712f6df 100644 --- a/drivers/media/i2c/mt9v111.c +++ b/drivers/media/i2c/mt9v111.c @@ -730,6 +730,9 @@ static int mt9v111_set_frame_interval(struct v4l2_subdev *sd, tpf->denominator; unsigned int max_fps; + if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + if (!tpf->numerator) tpf->numerator = 1; @@ -779,6 +782,9 @@ static int mt9v111_get_frame_interval(struct v4l2_subdev *sd, struct mt9v111_dev *mt9v111 = sd_to_mt9v111(sd); struct v4l2_fract *tpf = &ival->interval; + if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + mutex_lock(&mt9v111->stream_mutex); tpf->numerator = 1; diff --git a/drivers/media/i2c/ov2680.c b/drivers/media/i2c/ov2680.c index e1024e23c9cb..c1a3f4f0f3da 100644 --- a/drivers/media/i2c/ov2680.c +++ b/drivers/media/i2c/ov2680.c @@ -558,6 +558,9 @@ static int ov2680_get_frame_interval(struct v4l2_subdev *sd, { struct ov2680_dev *sensor = to_ov2680_dev(sd); + if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + mutex_lock(&sensor->lock); fi->interval = sensor->mode.frame_interval; mutex_unlock(&sensor->lock); diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c index 6e7c19a2af82..84873c02b9a5 100644 --- a/drivers/media/i2c/ov5640.c +++ b/drivers/media/i2c/ov5640.c @@ -3611,6 +3611,9 @@ static int ov5640_get_frame_interval(struct v4l2_subdev *sd, { struct ov5640_dev *sensor = to_ov5640_dev(sd); + if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + mutex_lock(&sensor->lock); fi->interval = sensor->frame_interval; mutex_unlock(&sensor->lock); @@ -3626,6 +3629,9 @@ static int ov5640_set_frame_interval(struct v4l2_subdev *sd, const struct ov5640_mode_info *mode; int frame_rate, ret = 0; + if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + if (fi->pad != 0) return -EINVAL; diff --git a/drivers/media/i2c/ov5648.c b/drivers/media/i2c/ov5648.c index 3c81953591d8..c1ce88540a42 100644 --- a/drivers/media/i2c/ov5648.c +++ b/drivers/media/i2c/ov5648.c @@ -2276,6 +2276,9 @@ static int ov5648_get_frame_interval(struct v4l2_subdev *subdev, const struct ov5648_mode *mode; int ret = 0; + if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + mutex_lock(&sensor->mutex); mode = sensor->state.mode; diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c index bff2f3fb9558..d8ff7c99fc72 100644 --- a/drivers/media/i2c/ov5693.c +++ b/drivers/media/i2c/ov5693.c @@ -1013,6 +1013,9 @@ static int ov5693_get_frame_interval(struct v4l2_subdev *sd, ov5693->ctrls.vblank->val); unsigned int fps = DIV_ROUND_CLOSEST(OV5693_PIXEL_RATE, framesize); + if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + interval->interval.numerator = 1; interval->interval.denominator = fps; diff --git a/drivers/media/i2c/ov6650.c b/drivers/media/i2c/ov6650.c index abf9e0467659..edacfd359ec9 100644 --- a/drivers/media/i2c/ov6650.c +++ b/drivers/media/i2c/ov6650.c @@ -806,6 +806,9 @@ static int ov6650_get_frame_interval(struct v4l2_subdev *sd, struct i2c_client *client = v4l2_get_subdevdata(sd); struct ov6650 *priv = to_ov6650(client); + 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 +826,9 @@ static int ov6650_set_frame_interval(struct v4l2_subdev *sd, struct v4l2_fract *tpf = &ival->interval; int div, ret; + if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + if (tpf->numerator == 0 || tpf->denominator == 0) div = 1; /* Reset to full rate */ else diff --git a/drivers/media/i2c/ov7251.c b/drivers/media/i2c/ov7251.c index d96cc26b918d..b4833f273250 100644 --- a/drivers/media/i2c/ov7251.c +++ b/drivers/media/i2c/ov7251.c @@ -1391,6 +1391,9 @@ static int ov7251_get_frame_interval(struct v4l2_subdev *subdev, { struct ov7251 *ov7251 = to_ov7251(subdev); + 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 +1409,9 @@ static int ov7251_set_frame_interval(struct v4l2_subdev *subdev, const struct ov7251_mode_info *new_mode; int ret = 0; + if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + mutex_lock(&ov7251->lock); new_mode = ov7251_find_mode_by_ival(ov7251, &fi->interval); diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c index 71175f918373..1056bccadb65 100644 --- a/drivers/media/i2c/ov7670.c +++ b/drivers/media/i2c/ov7670.c @@ -1161,6 +1161,8 @@ static int ov7670_get_frame_interval(struct v4l2_subdev *sd, { struct ov7670_info *info = to_state(sd); + if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; info->devtype->get_framerate(sd, &ival->interval); @@ -1174,6 +1176,8 @@ static int ov7670_set_frame_interval(struct v4l2_subdev *sd, struct v4l2_fract *tpf = &ival->interval; struct ov7670_info *info = to_state(sd); + if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; return info->devtype->set_framerate(sd, tpf); } diff --git a/drivers/media/i2c/ov772x.c b/drivers/media/i2c/ov772x.c index 59d3b8d006e4..4e226925020b 100644 --- a/drivers/media/i2c/ov772x.c +++ b/drivers/media/i2c/ov772x.c @@ -724,6 +724,9 @@ static int ov772x_get_frame_interval(struct v4l2_subdev *sd, struct ov772x_priv *priv = to_ov772x(sd); struct v4l2_fract *tpf = &ival->interval; + if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + tpf->numerator = 1; tpf->denominator = priv->fps; @@ -739,6 +742,9 @@ static int ov772x_set_frame_interval(struct v4l2_subdev *sd, unsigned int fps; int ret = 0; + if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + mutex_lock(&priv->lock); if (priv->streaming) { diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c index 0a9efa340771..d4d72536f722 100644 --- a/drivers/media/i2c/ov8865.c +++ b/drivers/media/i2c/ov8865.c @@ -2846,6 +2846,9 @@ static int ov8865_get_frame_interval(struct v4l2_subdev *subdev, unsigned int framesize; unsigned int fps; + if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + mutex_lock(&sensor->mutex); mode = sensor->state.mode; diff --git a/drivers/media/i2c/ov9650.c b/drivers/media/i2c/ov9650.c index 6b2de4220cf4..5cf6bb2bee9c 100644 --- a/drivers/media/i2c/ov9650.c +++ b/drivers/media/i2c/ov9650.c @@ -1107,6 +1107,9 @@ static int ov965x_get_frame_interval(struct v4l2_subdev *sd, { struct ov965x *ov965x = to_ov965x(sd); + if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + mutex_lock(&ov965x->lock); fi->interval = ov965x->fiv->interval; mutex_unlock(&ov965x->lock); @@ -1156,6 +1159,9 @@ static int ov965x_set_frame_interval(struct v4l2_subdev *sd, struct ov965x *ov965x = to_ov965x(sd); int ret; + 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); diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c index 236f63ac803d..c402bfea14ce 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c +++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c @@ -875,6 +875,9 @@ static int s5c73m3_oif_get_frame_interval(struct v4l2_subdev *sd, { struct s5c73m3 *state = oif_sd_to_s5c73m3(sd); + if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + if (fi->pad != OIF_SOURCE_PAD) return -EINVAL; @@ -926,6 +929,9 @@ static int s5c73m3_oif_set_frame_interval(struct v4l2_subdev *sd, struct s5c73m3 *state = oif_sd_to_s5c73m3(sd); int ret; + if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + if (fi->pad != OIF_SOURCE_PAD) return -EINVAL; diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c index 987d138fe022..5fc64cc04441 100644 --- a/drivers/media/i2c/s5k5baf.c +++ b/drivers/media/i2c/s5k5baf.c @@ -1124,6 +1124,9 @@ static int s5k5baf_get_frame_interval(struct v4l2_subdev *sd, { struct s5k5baf *state = to_s5k5baf(sd); + if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + mutex_lock(&state->lock); fi->interval.numerator = state->fiv; fi->interval.denominator = 10000; @@ -1162,6 +1165,9 @@ static int s5k5baf_set_frame_interval(struct v4l2_subdev *sd, { struct s5k5baf *state = to_s5k5baf(sd); + if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + mutex_lock(&state->lock); __s5k5baf_set_frame_interval(state, fi); mutex_unlock(&state->lock); diff --git a/drivers/media/i2c/tvp514x.c b/drivers/media/i2c/tvp514x.c index dee0cf992379..ae073a532eda 100644 --- a/drivers/media/i2c/tvp514x.c +++ b/drivers/media/i2c/tvp514x.c @@ -746,6 +746,8 @@ tvp514x_get_frame_interval(struct v4l2_subdev *sd, struct tvp514x_decoder *decoder = to_decoder(sd); enum tvp514x_std current_std; + if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; /* get the current standard */ current_std = decoder->current_std; @@ -765,6 +767,8 @@ tvp514x_set_frame_interval(struct v4l2_subdev *sd, struct v4l2_fract *timeperframe; enum tvp514x_std current_std; + if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; timeperframe = &ival->interval; diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index 4104445c546e..c45d60a87701 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -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, @@ -538,7 +537,7 @@ subdev_ioctl_get_state(struct v4l2_subdev *sd, struct v4l2_subdev_fh *subdev_fh, break; case VIDIOC_SUBDEV_G_FRAME_INTERVAL: case VIDIOC_SUBDEV_S_FRAME_INTERVAL: - which = V4L2_SUBDEV_FORMAT_ACTIVE; + which = ((struct v4l2_subdev_frame_interval *)arg)->which; break; case VIDIOC_SUBDEV_G_ROUTING: case VIDIOC_SUBDEV_S_ROUTING: @@ -789,6 +788,10 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg, if (!client_supports_streams) fi->stream = 0; + if (!(subdev_fh->client_caps & + V4L2_SUBDEV_CLIENT_CAP_WHICH_INTERVAL)) + fi->which = V4L2_SUBDEV_FORMAT_ACTIVE; + memset(fi->reserved, 0, sizeof(fi->reserved)); return v4l2_subdev_call(sd, pad, get_frame_interval, state, fi); } @@ -796,12 +799,16 @@ 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 (!(subdev_fh->client_caps & + V4L2_SUBDEV_CLIENT_CAP_WHICH_INTERVAL)) + fi->which = V4L2_SUBDEV_FORMAT_ACTIVE; + + 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); } diff --git a/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c b/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c index a6f66b483e02..2bff44846f39 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c @@ -500,6 +500,9 @@ static int gc0310_get_frame_interval(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_frame_interval *interval) { + if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + interval->interval.numerator = 1; interval->interval.denominator = GC0310_FPS; diff --git a/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c b/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c index 074f69e2b5e0..360341cecd62 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c @@ -704,6 +704,9 @@ static int gc2235_get_frame_interval(struct v4l2_subdev *sd, { struct gc2235_device *dev = to_gc2235_sensor(sd); + if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + interval->interval.numerator = 1; interval->interval.denominator = dev->res->fps; diff --git a/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c b/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c index 9f6404967e64..13b7797a7630 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c @@ -1394,6 +1394,9 @@ static int mt9m114_get_frame_interval(struct v4l2_subdev *sd, { struct mt9m114_device *dev = to_mt9m114_sensor(sd); + if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + interval->interval.numerator = 1; interval->interval.denominator = mt9m114_res[dev->res].fps; diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c index 5128c8ea6aed..6cc30e590a61 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c @@ -851,6 +851,9 @@ static int ov2722_get_frame_interval(struct v4l2_subdev *sd, { struct ov2722_device *dev = to_ov2722_sensor(sd); + if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + interval->interval.numerator = 1; interval->interval.denominator = dev->res->fps; diff --git a/drivers/staging/media/imx/imx-ic-prp.c b/drivers/staging/media/imx/imx-ic-prp.c index 6088a1aaa695..df04afc1b58b 100644 --- a/drivers/staging/media/imx/imx-ic-prp.c +++ b/drivers/staging/media/imx/imx-ic-prp.c @@ -401,6 +401,9 @@ static int prp_get_frame_interval(struct v4l2_subdev *sd, { struct prp_priv *priv = sd_to_priv(sd); + if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + if (fi->pad >= PRP_NUM_PADS) return -EINVAL; @@ -417,6 +420,9 @@ static int prp_set_frame_interval(struct v4l2_subdev *sd, { struct prp_priv *priv = sd_to_priv(sd); + if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + if (fi->pad >= PRP_NUM_PADS) return -EINVAL; diff --git a/drivers/staging/media/imx/imx-ic-prpencvf.c b/drivers/staging/media/imx/imx-ic-prpencvf.c index 50e748cd10df..2a6f8c207a9c 100644 --- a/drivers/staging/media/imx/imx-ic-prpencvf.c +++ b/drivers/staging/media/imx/imx-ic-prpencvf.c @@ -1211,6 +1211,9 @@ static int prp_get_frame_interval(struct v4l2_subdev *sd, { struct prp_priv *priv = sd_to_priv(sd); + if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + if (fi->pad >= PRPENCVF_NUM_PADS) return -EINVAL; @@ -1227,6 +1230,9 @@ static int prp_set_frame_interval(struct v4l2_subdev *sd, { struct prp_priv *priv = sd_to_priv(sd); + if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + if (fi->pad >= PRPENCVF_NUM_PADS) return -EINVAL; diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c index 96e351c9bf03..6c457b4b3167 100644 --- a/drivers/staging/media/imx/imx-media-csi.c +++ b/drivers/staging/media/imx/imx-media-csi.c @@ -908,6 +908,9 @@ static int csi_get_frame_interval(struct v4l2_subdev *sd, { struct csi_priv *priv = v4l2_get_subdevdata(sd); + if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + if (fi->pad >= CSI_NUM_PADS) return -EINVAL; @@ -928,6 +931,9 @@ static int csi_set_frame_interval(struct v4l2_subdev *sd, struct v4l2_fract *input_fi; int ret = 0; + if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + mutex_lock(&priv->lock); input_fi = &priv->frame_interval[CSI_SINK_PAD]; diff --git a/drivers/staging/media/imx/imx-media-vdic.c b/drivers/staging/media/imx/imx-media-vdic.c index 3c5224a6b910..6e6b9a4dbff2 100644 --- a/drivers/staging/media/imx/imx-media-vdic.c +++ b/drivers/staging/media/imx/imx-media-vdic.c @@ -786,6 +786,9 @@ static int vdic_get_frame_interval(struct v4l2_subdev *sd, { struct vdic_priv *priv = v4l2_get_subdevdata(sd); + if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + if (fi->pad >= VDIC_NUM_PADS) return -EINVAL; @@ -806,6 +809,9 @@ static int vdic_set_frame_interval(struct v4l2_subdev *sd, struct v4l2_fract *input_fi, *output_fi; int ret = 0; + if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + mutex_lock(&priv->lock); input_fi = &priv->frame_interval[priv->active_input_pad]; diff --git a/drivers/staging/media/tegra-video/csi.c b/drivers/staging/media/tegra-video/csi.c index 7594ec6465f0..b1d18bb7d022 100644 --- a/drivers/staging/media/tegra-video/csi.c +++ b/drivers/staging/media/tegra-video/csi.c @@ -231,6 +231,9 @@ static int tegra_csi_get_frame_interval(struct v4l2_subdev *subdev, if (!IS_ENABLED(CONFIG_VIDEO_TEGRA_TPG)) return -ENOIOCTLCMD; + if (vfi->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + vfi->interval.numerator = 1; vfi->interval.denominator = csi_chan->framerate; diff --git a/include/uapi/linux/v4l2-subdev.h b/include/uapi/linux/v4l2-subdev.h index 0401385fd8e9..c0ef7aeed721 100644 --- a/include/uapi/linux/v4l2-subdev.h +++ b/include/uapi/linux/v4l2-subdev.h @@ -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 */ @@ -241,6 +243,13 @@ struct v4l2_subdev_routing { */ #define V4L2_SUBDEV_CLIENT_CAP_STREAMS (1U << 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_WHICH_INTERVAL (1U << 1) + /** * struct v4l2_subdev_client_capability - Capabilities of the client accessing * the subdev From patchwork Tue Oct 24 00:51:29 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 13433815 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0D966C00A8F for ; Tue, 24 Oct 2023 01:07:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230284AbjJXBHw (ORCPT ); Mon, 23 Oct 2023 21:07:52 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39612 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231820AbjJXAvf (ORCPT ); Mon, 23 Oct 2023 20:51:35 -0400 Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0FD41120 for ; Mon, 23 Oct 2023 17:51:33 -0700 (PDT) Received: from pendragon.ideasonboard.com (213-243-189-158.bb.dnainternet.fi [213.243.189.158]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 184B1F02; Tue, 24 Oct 2023 02:51:16 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1698108676; bh=RFN+QpDv46gm2oi8tWpGpzjCGwNhdN1m5dt/qS0Z/5o=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=q8a4dH/1te6E9Lj2FApBx5/bM40AmTT31tIdL0/UQJN7DxHJ5Fwsfx6dOBdiEcHl/ oyHdCW+KMEQnruFm0iERPknagPawDP7rOflvgmk2qI+rObKRfvKIXu8GSFujm0Cc9g 3UfPaWFg+XqBdFJtTDAHb052iE2RnAaMBaqQ2SsM= From: Laurent Pinchart To: linux-media@vger.kernel.org Cc: Sakari Ailus , Hans Verkuil , Tomi Valkeinen , Hans de Goede Subject: [RFC PATCH v1 3/4] media: v4l2-subdev: Store frame interval in subdev state Date: Tue, 24 Oct 2023 03:51:29 +0300 Message-ID: <20231024005130.28026-4-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20231024005130.28026-1-laurent.pinchart@ideasonboard.com> References: <20231024005130.28026-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Subdev states store all standard pad configuration data, except for frame intervals. Fix it by adding interval fields in the v4l2_subdev_pad_config and v4l2_subdev_stream_config structures, with corresponding accessor functions and a helper function to implement the .get_frame_interval() operation. Signed-off-by: Laurent Pinchart --- drivers/media/v4l2-core/v4l2-subdev.c | 44 +++++++++++++++++++++ include/media/v4l2-subdev.h | 57 +++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index c45d60a87701..518f2f35c68d 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -1618,6 +1618,29 @@ int v4l2_subdev_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_state *state, } EXPORT_SYMBOL_GPL(v4l2_subdev_get_fmt); +int v4l2_subdev_get_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_frame_interval *fi) +{ + struct v4l2_fract *interval; + + if (sd->flags & V4L2_SUBDEV_FL_STREAMS) + interval = v4l2_subdev_state_get_stream_interval(state, fi->pad, + fi->stream); + else if (fi->pad < sd->entity.num_pads && fi->stream == 0) + interval = v4l2_subdev_get_pad_interval(sd, state, fi->pad); + else + interval = NULL; + + if (!interval) + return -EINVAL; + + fi->interval = *interval; + + return 0; +} +EXPORT_SYMBOL_GPL(v4l2_subdev_get_frame_interval); + int v4l2_subdev_set_routing(struct v4l2_subdev *sd, struct v4l2_subdev_state *state, const struct v4l2_subdev_krouting *routing) @@ -1761,6 +1784,27 @@ v4l2_subdev_state_get_stream_compose(struct v4l2_subdev_state *state, } EXPORT_SYMBOL_GPL(v4l2_subdev_state_get_stream_compose); +struct v4l2_fract * +v4l2_subdev_state_get_stream_interval(struct v4l2_subdev_state *state, + unsigned int pad, u32 stream) +{ + struct v4l2_subdev_stream_configs *stream_configs; + unsigned int i; + + lockdep_assert_held(state->lock); + + stream_configs = &state->stream_configs; + + for (i = 0; i < stream_configs->num_configs; ++i) { + if (stream_configs->configs[i].pad == pad && + stream_configs->configs[i].stream == stream) + return &stream_configs->configs[i].interval; + } + + return NULL; +} +EXPORT_SYMBOL_GPL(v4l2_subdev_state_get_stream_interval); + int v4l2_subdev_routing_find_opposite_end(const struct v4l2_subdev_krouting *routing, u32 pad, u32 stream, u32 *other_pad, u32 *other_stream) diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 962b546d0e3b..363f9a8a084c 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -681,11 +681,13 @@ struct v4l2_subdev_ir_ops { * @format: &struct v4l2_mbus_framefmt * @crop: &struct v4l2_rect to be used for crop * @compose: &struct v4l2_rect to be used for compose + * @interval: frame interval */ struct v4l2_subdev_pad_config { struct v4l2_mbus_framefmt format; struct v4l2_rect crop; struct v4l2_rect compose; + struct v4l2_fract interval; }; /** @@ -697,6 +699,7 @@ struct v4l2_subdev_pad_config { * @fmt: &struct v4l2_mbus_framefmt * @crop: &struct v4l2_rect to be used for crop * @compose: &struct v4l2_rect to be used for compose + * @interval: frame interval * * This structure stores configuration for a stream. */ @@ -708,6 +711,7 @@ struct v4l2_subdev_stream_config { struct v4l2_mbus_framefmt fmt; struct v4l2_rect crop; struct v4l2_rect compose; + struct v4l2_fract interval; }; /** @@ -1199,6 +1203,26 @@ v4l2_subdev_get_pad_compose(struct v4l2_subdev *sd, return &state->pads[pad].compose; } +/** + * v4l2_subdev_get_pad_interval - ancillary routine to get + * &struct v4l2_subdev_pad_config->interval + * + * @sd: pointer to &struct v4l2_subdev + * @state: pointer to &struct v4l2_subdev_state. + * @pad: index of the pad in the &struct v4l2_subdev_state->pads array. + */ +static inline struct v4l2_fract * +v4l2_subdev_get_pad_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + unsigned int pad) +{ + if (WARN_ON(!state)) + return NULL; + if (WARN_ON(pad >= sd->entity.num_pads)) + pad = 0; + return &state->pads[pad].interval; +} + /* * Temprary helpers until uses of v4l2_subdev_get_try_* functions have been * renamed @@ -1489,6 +1513,24 @@ v4l2_subdev_lock_and_get_active_state(struct v4l2_subdev *sd) int v4l2_subdev_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_state *state, struct v4l2_subdev_format *format); +/** + * v4l2_subdev_get_frame_interval() - Fill frame interval based on state + * @sd: subdevice + * @state: subdevice state + * @fi: pointer to &struct v4l2_subdev_frame_interval + * + * Fill @fi->interval field based on the information in the @fi struct. + * + * This function can be used by the subdev drivers which support active state to + * implement v4l2_subdev_pad_ops.get_frame_interval if the subdev driver does + * not need to do anything special in their get_frame_interval op. + * + * Returns 0 on success, error value otherwise. + */ +int v4l2_subdev_get_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_frame_interval *fi); + /** * v4l2_subdev_set_routing() - Set given routing to subdev state * @sd: The subdevice @@ -1580,6 +1622,21 @@ struct v4l2_rect * v4l2_subdev_state_get_stream_compose(struct v4l2_subdev_state *state, unsigned int pad, u32 stream); +/** + * v4l2_subdev_state_get_stream_interval() - Get pointer to a stream frame interval + * @state: subdevice state + * @pad: pad id + * @stream: stream id + * + * This returns a pointer to the frame interval for the given pad + stream in + * the subdev state. + * + * If the state does not contain the given pad + stream, NULL is returned. + */ +struct v4l2_fract * +v4l2_subdev_state_get_stream_interval(struct v4l2_subdev_state *state, + unsigned int pad, u32 stream); + /** * v4l2_subdev_routing_find_opposite_end() - Find the opposite stream * @routing: routing used to find the opposite side From patchwork Tue Oct 24 00:51:30 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 13433816 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7072FC25B6B for ; Tue, 24 Oct 2023 01:07:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231152AbjJXBHx (ORCPT ); Mon, 23 Oct 2023 21:07:53 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39538 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231824AbjJXAvf (ORCPT ); Mon, 23 Oct 2023 20:51:35 -0400 Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F319910E for ; Mon, 23 Oct 2023 17:51:32 -0700 (PDT) Received: from pendragon.ideasonboard.com (213-243-189-158.bb.dnainternet.fi [213.243.189.158]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 744B7128D; Tue, 24 Oct 2023 02:51:17 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1698108677; bh=To/N0JtBBDNKSyDB9ylDmIGcJHGess6jPoj9ixGYWCw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=J1qZa/FkKjVmP6QLor2A4ycvKO9HU+cByn5Hw/eNeZ9y2ITZpMGJZHWrQouvE96hP sJShbTtVmrZE198AHFA2NTD9XpFnCtj4oh71McJEEnkzcsevAeknNOPnGOA1qlnegV 1OZC9siIWVZFAjoENhFWOkDQej/7kARH772EmVVM= From: Laurent Pinchart To: linux-media@vger.kernel.org Cc: Sakari Ailus , Hans Verkuil , Tomi Valkeinen , Hans de Goede Subject: [RFC PATCH v1 4/4] media: i2c: thp7312: Store frame interval in subdev state Date: Tue, 24 Oct 2023 03:51:30 +0300 Message-ID: <20231024005130.28026-5-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20231024005130.28026-1-laurent.pinchart@ideasonboard.com> References: <20231024005130.28026-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Use the newly added storage for frame interval in the subdev state to simplify the driver. Signed-off-by: Laurent Pinchart --- drivers/media/i2c/thp7312.c | 145 ++++++++++++++++++++---------------- 1 file changed, 79 insertions(+), 66 deletions(-) diff --git a/drivers/media/i2c/thp7312.c b/drivers/media/i2c/thp7312.c index c5b1b6321633..28f869f69d02 100644 --- a/drivers/media/i2c/thp7312.c +++ b/drivers/media/i2c/thp7312.c @@ -278,10 +278,6 @@ struct thp7312_device { struct v4l2_ctrl_handler ctrl_handler; - /* These are protected by v4l2 active state */ - const struct thp7312_mode_info *current_mode; - const struct thp7312_frame_rate *current_rate; - struct { struct v4l2_ctrl *focus_auto; struct v4l2_ctrl *focus_absolute; @@ -329,6 +325,47 @@ static inline struct thp7312_device *to_thp7312_dev(struct v4l2_subdev *sd) return container_of(sd, struct thp7312_device, sd); } +static const struct thp7312_mode_info * +thp7312_find_mode(unsigned int width, unsigned int height, bool nearest) +{ + const struct thp7312_mode_info *mode; + + mode = v4l2_find_nearest_size(thp7312_mode_info_data, + ARRAY_SIZE(thp7312_mode_info_data), + width, height, width, height); + + if (!nearest && (mode->width != width || mode->height != height)) + return NULL; + + return mode; +} + +static const struct thp7312_frame_rate * +thp7312_find_rate(const struct thp7312_mode_info *mode, unsigned int fps, + bool nearest) +{ + const struct thp7312_frame_rate *best_rate = NULL; + const struct thp7312_frame_rate *rate; + unsigned int best_delta = UINT_MAX; + + if (!mode) + return NULL; + + for (rate = mode->rates; rate->fps && best_delta; ++rate) { + unsigned int delta = abs(rate->fps - fps); + + if (delta <= best_delta) { + best_delta = delta; + best_rate = rate; + } + } + + if (!nearest && best_delta) + return NULL; + + return best_rate; +} + /* ----------------------------------------------------------------------------- * Device Access & Configuration */ @@ -475,17 +512,30 @@ static int thp7312_set_framefmt(struct thp7312_device *thp7312, static int thp7312_init_mode(struct thp7312_device *thp7312, struct v4l2_subdev_state *sd_state) { + const struct thp7312_mode_info *mode; + const struct thp7312_frame_rate *rate; struct v4l2_mbus_framefmt *fmt; + struct v4l2_fract *interval; int ret; + /* + * TODO: The mode and rate should be cached in the subdev state, once + * support for extending states will be available. + */ fmt = v4l2_subdev_get_pad_format(&thp7312->sd, sd_state, 0); + interval = v4l2_subdev_get_pad_interval(&thp7312->sd, sd_state, 0); + + mode = thp7312_find_mode(fmt->width, fmt->height, false); + rate = thp7312_find_rate(mode, interval->denominator, false); + + if (WARN_ON(!mode || !rate)) + return -EINVAL; ret = thp7312_set_framefmt(thp7312, fmt); if (ret) return ret; - return thp7312_change_mode(thp7312, thp7312->current_mode, - thp7312->current_rate); + return thp7312_change_mode(thp7312, mode, rate); } static int thp7312_stream_enable(struct thp7312_device *thp7312, int enable) @@ -703,21 +753,6 @@ static bool thp7312_find_bus_code(u32 code) return false; } -static const struct thp7312_mode_info * -thp7312_find_mode(unsigned int width, unsigned int height, bool nearest) -{ - const struct thp7312_mode_info *mode; - - mode = v4l2_find_nearest_size(thp7312_mode_info_data, - ARRAY_SIZE(thp7312_mode_info_data), - width, height, width, height); - - if (!nearest && (mode->width != width || mode->height != height)) - return NULL; - - return mode; -} - static int thp7312_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_mbus_code_enum *code) @@ -781,6 +816,7 @@ static int thp7312_set_fmt(struct v4l2_subdev *sd, struct thp7312_device *thp7312 = to_thp7312_dev(sd); struct v4l2_mbus_framefmt *mbus_fmt = &format->format; struct v4l2_mbus_framefmt *fmt; + struct v4l2_fract *interval; const struct thp7312_mode_info *mode; if (!thp7312_find_bus_code(mbus_fmt->code)) @@ -800,37 +836,22 @@ static int thp7312_set_fmt(struct v4l2_subdev *sd, *mbus_fmt = *fmt; - if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) { - thp7312->current_mode = mode; - thp7312->current_rate = &mode->rates[0]; - } + interval = v4l2_subdev_get_pad_interval(sd, sd_state, 0); + interval->numerator = 1; + interval->denominator = mode->rates[0].fps; return 0; } -static int thp7312_g_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *fi) -{ - struct thp7312_device *thp7312 = to_thp7312_dev(sd); - struct v4l2_subdev_state *sd_state; - - sd_state = v4l2_subdev_lock_and_get_active_state(sd); - fi->interval.numerator = 1; - fi->interval.denominator = thp7312->current_rate->fps; - v4l2_subdev_unlock_state(sd_state); - - return 0; -} - -static int thp7312_s_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *fi) +static int thp7312_set_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval *fi) { struct thp7312_device *thp7312 = to_thp7312_dev(sd); const struct thp7312_mode_info *mode; - const struct thp7312_frame_rate *best_rate = NULL; const struct thp7312_frame_rate *rate; - struct v4l2_subdev_state *sd_state; - unsigned int best_delta = UINT_MAX; + const struct v4l2_mbus_framefmt *fmt; + struct v4l2_fract *interval; unsigned int fps; /* Avoid divisions by 0, pick the highest frame if the interval is 0. */ @@ -838,25 +859,15 @@ static int thp7312_s_frame_interval(struct v4l2_subdev *sd, ? DIV_ROUND_CLOSEST(fi->interval.denominator, fi->interval.numerator) : UINT_MAX; - sd_state = v4l2_subdev_lock_and_get_active_state(sd); + fmt = v4l2_subdev_get_pad_format(&thp7312->sd, sd_state, 0); + mode = thp7312_find_mode(fmt->width, fmt->height, false); + rate = thp7312_find_rate(mode, fps, true); - mode = thp7312->current_mode; + interval = v4l2_subdev_get_pad_interval(sd, sd_state, 0); + interval->numerator = 1; + interval->denominator = rate->fps; - for (rate = mode->rates; rate->fps && best_delta; ++rate) { - unsigned int delta = abs(rate->fps - fps); - - if (delta <= best_delta) { - best_delta = delta; - best_rate = rate; - } - } - - thp7312->current_rate = best_rate; - - v4l2_subdev_unlock_state(sd_state); - - fi->interval.numerator = 1; - fi->interval.denominator = best_rate->fps; + fi->interval = *interval; return 0; } @@ -911,8 +922,10 @@ static int thp7312_init_cfg(struct v4l2_subdev *sd, { const struct thp7312_mode_info *default_mode = &thp7312_mode_info_data[0]; struct v4l2_mbus_framefmt *fmt; + struct v4l2_fract *interval; fmt = v4l2_subdev_get_pad_format(sd, sd_state, 0); + interval = v4l2_subdev_get_pad_interval(sd, sd_state, 0); /* * default init sequence initialize thp7312 to @@ -927,6 +940,9 @@ static int thp7312_init_cfg(struct v4l2_subdev *sd, fmt->height = default_mode->height; fmt->field = V4L2_FIELD_NONE; + interval->numerator = 1; + interval->denominator = default_mode->rates[0].fps; + return 0; } @@ -937,8 +953,6 @@ static const struct v4l2_subdev_core_ops thp7312_core_ops = { }; static const struct v4l2_subdev_video_ops thp7312_video_ops = { - .g_frame_interval = thp7312_g_frame_interval, - .s_frame_interval = thp7312_s_frame_interval, .s_stream = thp7312_s_stream, }; @@ -947,6 +961,8 @@ static const struct v4l2_subdev_pad_ops thp7312_pad_ops = { .init_cfg = thp7312_init_cfg, .get_fmt = v4l2_subdev_get_fmt, .set_fmt = thp7312_set_fmt, + .get_frame_interval = v4l2_subdev_get_frame_interval, + .set_frame_interval = thp7312_set_frame_interval, .enum_frame_size = thp7312_enum_frame_size, .enum_frame_interval = thp7312_enum_frame_interval, }; @@ -2234,9 +2250,6 @@ static int thp7312_probe(struct i2c_client *client) if (thp7312->boot_mode == THP7312_BOOT_MODE_2WIRE_SLAVE) return thp7312_register_flash_mode(thp7312); - thp7312->current_mode = &thp7312_mode_info_data[0]; - thp7312->current_rate = &thp7312->current_mode->rates[0]; - ret = thp7312_init_sensors(thp7312); if (ret < 0) return ret;