diff mbox series

[v4l-utils,v1,1/3] libv4l2subdev: Extend API with 'which' argument where missing

Message ID 20240610012238.30462-2-laurent.pinchart@ideasonboard.com (mailing list archive)
State New
Headers show
Series media-ctl: Add support for subdev TRY state | expand

Commit Message

Laurent Pinchart June 10, 2024, 1:22 a.m. UTC
Many functions exposed by libv4l2subdev have been added over time
hardcoding usage of the V4L2_SUBDEV_FORMAT_ACTIVE state. Extend them
with a 'which' argument to allow callers to access the TRY state as
well. Update existing callers to pass V4L2_SUBDEV_FORMAT_ACTIVE
unconditionally, preserving the existing behaviour.

To support accessing the TRY state when getting or setting frame
intervals, set the V4L2_SUBDEV_CLIENT_CAP_INTERVAL_USES_WHICH client
capability.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 utils/media-ctl/libv4l2subdev.c | 65 +++++++++++++++++++++------------
 utils/media-ctl/media-ctl.c     | 11 ++++--
 utils/media-ctl/v4l2subdev.h    | 49 ++++++++++++++++++++++---
 3 files changed, 92 insertions(+), 33 deletions(-)

Comments

Tomi Valkeinen June 10, 2024, 6:08 a.m. UTC | #1
On 10/06/2024 04:22, Laurent Pinchart wrote:
> Many functions exposed by libv4l2subdev have been added over time
> hardcoding usage of the V4L2_SUBDEV_FORMAT_ACTIVE state. Extend them
> with a 'which' argument to allow callers to access the TRY state as
> well. Update existing callers to pass V4L2_SUBDEV_FORMAT_ACTIVE
> unconditionally, preserving the existing behaviour.
> 
> To support accessing the TRY state when getting or setting frame
> intervals, set the V4L2_SUBDEV_CLIENT_CAP_INTERVAL_USES_WHICH client
> capability.

I would have split this one to a separate patch, but not a biggie.

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>

  Tomi

> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>   utils/media-ctl/libv4l2subdev.c | 65 +++++++++++++++++++++------------
>   utils/media-ctl/media-ctl.c     | 11 ++++--
>   utils/media-ctl/v4l2subdev.h    | 49 ++++++++++++++++++++++---
>   3 files changed, 92 insertions(+), 33 deletions(-)
> 
> diff --git a/utils/media-ctl/libv4l2subdev.c b/utils/media-ctl/libv4l2subdev.c
> index e0df686e01c7..163fd610dce7 100644
> --- a/utils/media-ctl/libv4l2subdev.c
> +++ b/utils/media-ctl/libv4l2subdev.c
> @@ -69,7 +69,8 @@ int v4l2_subdev_open(struct media_entity *entity)
>   	ret = ioctl(entity->fd, VIDIOC_SUBDEV_QUERYCAP, &subdevcap);
>   	subdev_streams = !ret && (subdevcap.capabilities & V4L2_SUBDEV_CAP_STREAMS);
>   
> -	clientcap.capabilities = V4L2_SUBDEV_CLIENT_CAP_STREAMS;
> +	clientcap.capabilities = V4L2_SUBDEV_CLIENT_CAP_STREAMS
> +			       | V4L2_SUBDEV_CLIENT_CAP_INTERVAL_USES_WHICH;
>   
>   	ret = ioctl(entity->fd, VIDIOC_SUBDEV_S_CLIENT_CAP, &clientcap);
>   	client_streams = !ret && (clientcap.capabilities & V4L2_SUBDEV_CLIENT_CAP_STREAMS);
> @@ -240,10 +241,11 @@ int v4l2_subdev_set_selection(struct media_entity *entity,
>   
>   int v4l2_subdev_get_routing(struct media_entity *entity,
>   			    struct v4l2_subdev_route **routes,
> -			    unsigned int *num_routes)
> +			    unsigned int *num_routes,
> +			    enum v4l2_subdev_format_whence which)
>   {
>   	struct v4l2_subdev_routing routing = {
> -		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
> +		.which = which,
>   	};
>   	struct v4l2_subdev_route *r;
>   	int ret;
> @@ -287,10 +289,11 @@ int v4l2_subdev_get_routing(struct media_entity *entity,
>   
>   int v4l2_subdev_set_routing(struct media_entity *entity,
>   			    struct v4l2_subdev_route *routes,
> -			    unsigned int num_routes)
> +			    unsigned int num_routes,
> +			    enum v4l2_subdev_format_whence which)
>   {
>   	struct v4l2_subdev_routing routing = {
> -		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
> +		.which = which,
>   		.routes = (uintptr_t)routes,
>   		.num_routes = num_routes,
>   		.len_routes = num_routes,
> @@ -387,7 +390,8 @@ int v4l2_subdev_set_dv_timings(struct media_entity *entity,
>   
>   int v4l2_subdev_get_frame_interval(struct media_entity *entity,
>   				   struct v4l2_fract *interval,
> -				   unsigned int pad, unsigned int stream)
> +				   unsigned int pad, unsigned int stream,
> +				   enum v4l2_subdev_format_whence which)
>   {
>   	struct v4l2_subdev_frame_interval ival;
>   	int ret;
> @@ -404,6 +408,7 @@ int v4l2_subdev_get_frame_interval(struct media_entity *entity,
>   	memset(&ival, 0, sizeof(ival));
>   	ival.pad = pad;
>   	ival.stream = stream;
> +	ival.which = which;
>   
>   	ret = ioctl(entity->fd, VIDIOC_SUBDEV_G_FRAME_INTERVAL, &ival);
>   	if (ret < 0)
> @@ -415,7 +420,8 @@ int v4l2_subdev_get_frame_interval(struct media_entity *entity,
>   
>   int v4l2_subdev_set_frame_interval(struct media_entity *entity,
>   				   struct v4l2_fract *interval,
> -				   unsigned int pad, unsigned int stream)
> +				   unsigned int pad, unsigned int stream,
> +				   enum v4l2_subdev_format_whence which)
>   {
>   	struct v4l2_subdev_frame_interval ival;
>   	int ret;
> @@ -433,6 +439,7 @@ int v4l2_subdev_set_frame_interval(struct media_entity *entity,
>   	ival.pad = pad;
>   	ival.stream = stream;
>   	ival.interval = *interval;
> +	ival.which = which;
>   
>   	ret = ioctl(entity->fd, VIDIOC_SUBDEV_S_FRAME_INTERVAL, &ival);
>   	if (ret < 0)
> @@ -514,7 +521,9 @@ static int v4l2_subdev_parse_setup_route(struct media_device *media,
>   	return 0;
>   }
>   
> -int v4l2_subdev_parse_setup_routes(struct media_device *media, const char *p)
> +int v4l2_subdev_parse_setup_routes(struct media_device *media,
> +				   enum v4l2_subdev_format_whence which,
> +				   const char *p)
>   {
>   	struct media_entity *entity;
>   	struct v4l2_subdev_route *routes;
> @@ -578,7 +587,7 @@ int v4l2_subdev_parse_setup_routes(struct media_device *media, const char *p)
>   			  r->flags);
>   	}
>   
> -	ret = v4l2_subdev_set_routing(entity, routes, num_routes);
> +	ret = v4l2_subdev_set_routing(entity, routes, num_routes, which);
>   	if (ret) {
>   		media_dbg(entity->media, "VIDIOC_SUBDEV_S_ROUTING failed: %d\n",
>   			  ret);
> @@ -961,7 +970,8 @@ static struct media_pad *v4l2_subdev_parse_pad_format(
>   
>   static int set_format(struct media_pad *pad,
>   		      unsigned int stream,
> -		      struct v4l2_mbus_framefmt *format)
> +		      struct v4l2_mbus_framefmt *format,
> +		      enum v4l2_subdev_format_whence which)
>   {
>   	int ret;
>   
> @@ -975,7 +985,7 @@ static int set_format(struct media_pad *pad,
>   		  pad->entity->info.name, pad->index, stream);
>   
>   	ret = v4l2_subdev_set_format(pad->entity, format, pad->index, stream,
> -				     V4L2_SUBDEV_FORMAT_ACTIVE);
> +				     which);
>   	if (ret < 0) {
>   		media_dbg(pad->entity->media,
>   			  "Unable to set format: %s (%d)\n",
> @@ -992,7 +1002,8 @@ static int set_format(struct media_pad *pad,
>   }
>   
>   static int set_selection(struct media_pad *pad, unsigned int stream,
> -			 unsigned int target, struct v4l2_rect *rect)
> +			 unsigned int target, struct v4l2_rect *rect,
> +			 enum v4l2_subdev_format_whence which)
>   {
>   	int ret;
>   
> @@ -1005,7 +1016,7 @@ static int set_selection(struct media_pad *pad, unsigned int stream,
>   		  pad->entity->info.name, pad->index, stream);
>   
>   	ret = v4l2_subdev_set_selection(pad->entity, rect, pad->index, stream,
> -					target, V4L2_SUBDEV_FORMAT_ACTIVE);
> +					target, which);
>   	if (ret < 0) {
>   		media_dbg(pad->entity->media,
>   			  "Unable to set selection rectangle: %s (%d)\n",
> @@ -1021,7 +1032,8 @@ static int set_selection(struct media_pad *pad, unsigned int stream,
>   }
>   
>   static int set_frame_interval(struct media_pad *pad, unsigned int stream,
> -			      struct v4l2_fract *interval)
> +			      struct v4l2_fract *interval,
> +			      enum v4l2_subdev_format_whence which)
>   {
>   	int ret;
>   
> @@ -1034,7 +1046,7 @@ static int set_frame_interval(struct media_pad *pad, unsigned int stream,
>   		  pad->entity->info.name, pad->index, stream);
>   
>   	ret = v4l2_subdev_set_frame_interval(pad->entity, interval, pad->index,
> -					     stream);
> +					     stream, which);
>   	if (ret < 0) {
>   		media_dbg(pad->entity->media,
>   			  "Unable to set frame interval: %s (%d)",
> @@ -1050,6 +1062,7 @@ static int set_frame_interval(struct media_pad *pad, unsigned int stream,
>   
>   
>   static int v4l2_subdev_parse_setup_format(struct media_device *media,
> +					  enum v4l2_subdev_format_whence which,
>   					  const char *p, char **endp)
>   {
>   	struct v4l2_mbus_framefmt format = { 0, 0, 0 };
> @@ -1072,26 +1085,26 @@ static int v4l2_subdev_parse_setup_format(struct media_device *media,
>   	}
>   
>   	if (pad->flags & MEDIA_PAD_FL_SINK) {
> -		ret = set_format(pad, stream, &format);
> +		ret = set_format(pad, stream, &format, which);
>   		if (ret < 0)
>   			return ret;
>   	}
>   
> -	ret = set_selection(pad, stream, V4L2_SEL_TGT_CROP, &crop);
> +	ret = set_selection(pad, stream, V4L2_SEL_TGT_CROP, &crop, which);
>   	if (ret < 0)
>   		return ret;
>   
> -	ret = set_selection(pad, stream, V4L2_SEL_TGT_COMPOSE, &compose);
> +	ret = set_selection(pad, stream, V4L2_SEL_TGT_COMPOSE, &compose, which);
>   	if (ret < 0)
>   		return ret;
>   
>   	if (pad->flags & MEDIA_PAD_FL_SOURCE) {
> -		ret = set_format(pad, stream, &format);
> +		ret = set_format(pad, stream, &format, which);
>   		if (ret < 0)
>   			return ret;
>   	}
>   
> -	ret = set_frame_interval(pad, stream, &interval);
> +	ret = set_frame_interval(pad, stream, &interval, which);
>   	if (ret < 0)
>   		return ret;
>   
> @@ -1109,9 +1122,11 @@ static int v4l2_subdev_parse_setup_format(struct media_device *media,
>   			if (link->source == pad &&
>   			    link->sink->entity->info.type == MEDIA_ENT_T_V4L2_SUBDEV) {
>   				remote_format = format;
> -				set_format(link->sink, stream, &remote_format);
> +				set_format(link->sink, stream, &remote_format,
> +					   which);
>   
> -				ret = set_frame_interval(link->sink, stream, &interval);
> +				ret = set_frame_interval(link->sink, stream,
> +							 &interval, which);
>   				if (ret < 0 && ret != -EINVAL && ret != -ENOTTY)
>   					return ret;
>   			}
> @@ -1122,13 +1137,15 @@ static int v4l2_subdev_parse_setup_format(struct media_device *media,
>   	return 0;
>   }
>   
> -int v4l2_subdev_parse_setup_formats(struct media_device *media, const char *p)
> +int v4l2_subdev_parse_setup_formats(struct media_device *media,
> +				    enum v4l2_subdev_format_whence which,
> +				    const char *p)
>   {
>   	char *end;
>   	int ret;
>   
>   	do {
> -		ret = v4l2_subdev_parse_setup_format(media, p, &end);
> +		ret = v4l2_subdev_parse_setup_format(media, which, p, &end);
>   		if (ret < 0)
>   			return ret;
>   
> diff --git a/utils/media-ctl/media-ctl.c b/utils/media-ctl/media-ctl.c
> index 1a9e393ac1f3..44256df953db 100644
> --- a/utils/media-ctl/media-ctl.c
> +++ b/utils/media-ctl/media-ctl.c
> @@ -108,7 +108,8 @@ static void v4l2_subdev_print_format(struct media_entity *entity,
>   	if (ret != 0)
>   		return;
>   
> -	ret = v4l2_subdev_get_frame_interval(entity, &interval, pad, stream);
> +	ret = v4l2_subdev_get_frame_interval(entity, &interval, pad, stream,
> +					     V4L2_SUBDEV_FORMAT_ACTIVE);
>   	if (ret != 0 && ret != -ENOTTY && ret != -EINVAL)
>   		return;
>   
> @@ -527,7 +528,8 @@ static void media_print_topology_text_entity(struct media_device *media,
>   	unsigned int padding;
>   
>   	if (media_entity_type(entity) == MEDIA_ENT_T_V4L2_SUBDEV)
> -		v4l2_subdev_get_routing(entity, &routes, &num_routes);
> +		v4l2_subdev_get_routing(entity, &routes, &num_routes,
> +					V4L2_SUBDEV_FORMAT_ACTIVE);
>   
>   	padding = printf("- entity %u: ", info->id);
>   	printf("%s (%u pad%s, %u link%s", info->name,
> @@ -738,7 +740,9 @@ int main(int argc, char **argv)
>   	}
>   
>   	if (media_opts.routes) {
> -		ret = v4l2_subdev_parse_setup_routes(media, media_opts.routes);
> +		ret = v4l2_subdev_parse_setup_routes(media,
> +						     V4L2_SUBDEV_FORMAT_ACTIVE,
> +						     media_opts.routes);
>   		if (ret) {
>   			printf("Unable to setup routes: %s (%d)\n",
>   			       strerror(-ret), -ret);
> @@ -748,6 +752,7 @@ int main(int argc, char **argv)
>   
>   	if (media_opts.formats) {
>   		ret = v4l2_subdev_parse_setup_formats(media,
> +						      V4L2_SUBDEV_FORMAT_ACTIVE,
>   						      media_opts.formats);
>   		if (ret) {
>   			printf("Unable to setup formats: %s (%d)\n",
> diff --git a/utils/media-ctl/v4l2subdev.h b/utils/media-ctl/v4l2subdev.h
> index 1277040bfeae..0c1feae28e88 100644
> --- a/utils/media-ctl/v4l2subdev.h
> +++ b/utils/media-ctl/v4l2subdev.h
> @@ -142,32 +142,44 @@ int v4l2_subdev_set_selection(struct media_entity *entity,
>    * @param entity - subdev-device media entity.
>    * @param routes - routes of the subdev.
>    * @param num_routes - number of routes.
> + * @param which - identifier of the routes to get.
>    *
>    * Get the routes of @a entity and return them in an allocated array in @a routes
>    * and the number of routes in @a num_routes.
>    *
>    * The caller is responsible for freeing the routes array after use.
>    *
> + * @a which is set to V4L2_SUBDEV_FORMAT_TRY to get the routing table stored in
> + * the file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to get the device's active
> + * routing table.
> + *
>    * @return 0 on success, or a negative error code on failure.
>    */
>   int v4l2_subdev_get_routing(struct media_entity *entity,
>   			    struct v4l2_subdev_route **routes,
> -			    unsigned int *num_routes);
> +			    unsigned int *num_routes,
> +			    enum v4l2_subdev_format_whence which);
>   
>   /**
>    * @brief Set the routing table of a subdev media entity.
>    * @param entity - subdev-device media entity.
>    * @param routes - routes of the subdev.
>    * @param num_routes - number of routes.
> + * @param which - identifier of the routes to set.
>    *
>    * Set the routes of @a entity. The routes are given in @a routes with the
>    * length of @a num_routes.
>    *
> + * @a which is set to V4L2_SUBDEV_FORMAT_TRY to set the routing table stored in
> + * the file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to set the device's active
> + * routing table.
> + *
>    * @return 0 on success, or a negative error code on failure.
>    */
>   int v4l2_subdev_set_routing(struct media_entity *entity,
>   			    struct v4l2_subdev_route *route,
> -			    unsigned int num_routes);
> +			    unsigned int num_routes,
> +			    enum v4l2_subdev_format_whence which);
>   
>   /**
>    * @brief Query the digital video capabilities of a pad.
> @@ -228,6 +240,7 @@ int v4l2_subdev_set_dv_timings(struct media_entity *entity,
>    * @param interval - frame interval to be filled.
>    * @param pad - pad number.
>    * @param stream - stream number.
> + * @param which - identifier of the interval to get.
>    *
>    * Retrieve the current frame interval on subdev @a entity and store it in the
>    * @a interval structure.
> @@ -235,11 +248,16 @@ int v4l2_subdev_set_dv_timings(struct media_entity *entity,
>    * Frame interval retrieving is usually supported only on devices at the
>    * beginning of video pipelines, such as sensors.
>    *
> + * @a which is set to V4L2_SUBDEV_FORMAT_TRY to get the frame interval stored
> + * in the file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to get the device's active
> + * frame interval.
> + *
>    * @return 0 on success, or a negative error code on failure.
>    */
>   
>   int v4l2_subdev_get_frame_interval(struct media_entity *entity,
> -	struct v4l2_fract *interval, unsigned int pad, unsigned int stream);
> +	struct v4l2_fract *interval, unsigned int pad, unsigned int stream,
> +	enum v4l2_subdev_format_whence which);
>   
>   /**
>    * @brief Set the frame interval on a sub-device.
> @@ -247,6 +265,7 @@ int v4l2_subdev_get_frame_interval(struct media_entity *entity,
>    * @param interval - frame interval.
>    * @param pad - pad number.
>    * @param stream - stream number.
> + * @param which - identifier of the interval to set.
>    *
>    * Set the frame interval on subdev @a entity to @a interval. The driver is
>    * allowed to modify the requested frame interval, in which case @a interval is
> @@ -255,14 +274,20 @@ int v4l2_subdev_get_frame_interval(struct media_entity *entity,
>    * Frame interval setting is usually supported only on devices at the beginning
>    * of video pipelines, such as sensors.
>    *
> + * @a which is set to V4L2_SUBDEV_FORMAT_TRY to set the frame interval stored
> + * in the file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to set the device's active
> + * frame interval.
> + *
>    * @return 0 on success, or a negative error code on failure.
>    */
>   int v4l2_subdev_set_frame_interval(struct media_entity *entity,
> -	struct v4l2_fract *interval, unsigned int pad, unsigned int stream);
> +	struct v4l2_fract *interval, unsigned int pad, unsigned int stream,
> +	enum v4l2_subdev_format_whence which);
>   
>   /**
>    * @brief Parse a string and apply format, crop and frame interval settings.
>    * @param media - media device.
> + * @param which - identifier of the parameters to set.
>    * @param p - input string
>    * @param endp - pointer to string p where parsing ended (return)
>    *
> @@ -272,20 +297,32 @@ int v4l2_subdev_set_frame_interval(struct media_entity *entity,
>    *
>    * Format strings are separeted by commas (,).
>    *
> + * @a which is set to V4L2_SUBDEV_FORMAT_TRY to set the parameters stored in the
> + * file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to set the device's active
> + * parameters.
> + *
>    * @return 0 on success, or a negative error code on failure.
>    */
> -int v4l2_subdev_parse_setup_formats(struct media_device *media, const char *p);
> +int v4l2_subdev_parse_setup_formats(struct media_device *media,
> +				    enum v4l2_subdev_format_whence which,
> +				    const char *p);
>   
>   /**
>    * @brief Parse a string and apply route settings.
>    * @param media - media device.
> + * @param which - identifier of the routes to set.
>    * @param p - input string
>    *
>    * Parse string @a p and apply route settings to a subdev.
>    *
> + * @a which is set to V4L2_SUBDEV_FORMAT_TRY to set the routes stored in the
> + * file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to set the device's active routes.
> + *
>    * @return 0 on success, or a negative error code on failure.
>    */
> -int v4l2_subdev_parse_setup_routes(struct media_device *media, const char *p);
> +int v4l2_subdev_parse_setup_routes(struct media_device *media,
> +				   enum v4l2_subdev_format_whence which,
> +				   const char *p);
>   
>   /**
>    * @brief Convert media bus pixel code to string.
diff mbox series

Patch

diff --git a/utils/media-ctl/libv4l2subdev.c b/utils/media-ctl/libv4l2subdev.c
index e0df686e01c7..163fd610dce7 100644
--- a/utils/media-ctl/libv4l2subdev.c
+++ b/utils/media-ctl/libv4l2subdev.c
@@ -69,7 +69,8 @@  int v4l2_subdev_open(struct media_entity *entity)
 	ret = ioctl(entity->fd, VIDIOC_SUBDEV_QUERYCAP, &subdevcap);
 	subdev_streams = !ret && (subdevcap.capabilities & V4L2_SUBDEV_CAP_STREAMS);
 
-	clientcap.capabilities = V4L2_SUBDEV_CLIENT_CAP_STREAMS;
+	clientcap.capabilities = V4L2_SUBDEV_CLIENT_CAP_STREAMS
+			       | V4L2_SUBDEV_CLIENT_CAP_INTERVAL_USES_WHICH;
 
 	ret = ioctl(entity->fd, VIDIOC_SUBDEV_S_CLIENT_CAP, &clientcap);
 	client_streams = !ret && (clientcap.capabilities & V4L2_SUBDEV_CLIENT_CAP_STREAMS);
@@ -240,10 +241,11 @@  int v4l2_subdev_set_selection(struct media_entity *entity,
 
 int v4l2_subdev_get_routing(struct media_entity *entity,
 			    struct v4l2_subdev_route **routes,
-			    unsigned int *num_routes)
+			    unsigned int *num_routes,
+			    enum v4l2_subdev_format_whence which)
 {
 	struct v4l2_subdev_routing routing = {
-		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
+		.which = which,
 	};
 	struct v4l2_subdev_route *r;
 	int ret;
@@ -287,10 +289,11 @@  int v4l2_subdev_get_routing(struct media_entity *entity,
 
 int v4l2_subdev_set_routing(struct media_entity *entity,
 			    struct v4l2_subdev_route *routes,
-			    unsigned int num_routes)
+			    unsigned int num_routes,
+			    enum v4l2_subdev_format_whence which)
 {
 	struct v4l2_subdev_routing routing = {
-		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
+		.which = which,
 		.routes = (uintptr_t)routes,
 		.num_routes = num_routes,
 		.len_routes = num_routes,
@@ -387,7 +390,8 @@  int v4l2_subdev_set_dv_timings(struct media_entity *entity,
 
 int v4l2_subdev_get_frame_interval(struct media_entity *entity,
 				   struct v4l2_fract *interval,
-				   unsigned int pad, unsigned int stream)
+				   unsigned int pad, unsigned int stream,
+				   enum v4l2_subdev_format_whence which)
 {
 	struct v4l2_subdev_frame_interval ival;
 	int ret;
@@ -404,6 +408,7 @@  int v4l2_subdev_get_frame_interval(struct media_entity *entity,
 	memset(&ival, 0, sizeof(ival));
 	ival.pad = pad;
 	ival.stream = stream;
+	ival.which = which;
 
 	ret = ioctl(entity->fd, VIDIOC_SUBDEV_G_FRAME_INTERVAL, &ival);
 	if (ret < 0)
@@ -415,7 +420,8 @@  int v4l2_subdev_get_frame_interval(struct media_entity *entity,
 
 int v4l2_subdev_set_frame_interval(struct media_entity *entity,
 				   struct v4l2_fract *interval,
-				   unsigned int pad, unsigned int stream)
+				   unsigned int pad, unsigned int stream,
+				   enum v4l2_subdev_format_whence which)
 {
 	struct v4l2_subdev_frame_interval ival;
 	int ret;
@@ -433,6 +439,7 @@  int v4l2_subdev_set_frame_interval(struct media_entity *entity,
 	ival.pad = pad;
 	ival.stream = stream;
 	ival.interval = *interval;
+	ival.which = which;
 
 	ret = ioctl(entity->fd, VIDIOC_SUBDEV_S_FRAME_INTERVAL, &ival);
 	if (ret < 0)
@@ -514,7 +521,9 @@  static int v4l2_subdev_parse_setup_route(struct media_device *media,
 	return 0;
 }
 
-int v4l2_subdev_parse_setup_routes(struct media_device *media, const char *p)
+int v4l2_subdev_parse_setup_routes(struct media_device *media,
+				   enum v4l2_subdev_format_whence which,
+				   const char *p)
 {
 	struct media_entity *entity;
 	struct v4l2_subdev_route *routes;
@@ -578,7 +587,7 @@  int v4l2_subdev_parse_setup_routes(struct media_device *media, const char *p)
 			  r->flags);
 	}
 
-	ret = v4l2_subdev_set_routing(entity, routes, num_routes);
+	ret = v4l2_subdev_set_routing(entity, routes, num_routes, which);
 	if (ret) {
 		media_dbg(entity->media, "VIDIOC_SUBDEV_S_ROUTING failed: %d\n",
 			  ret);
@@ -961,7 +970,8 @@  static struct media_pad *v4l2_subdev_parse_pad_format(
 
 static int set_format(struct media_pad *pad,
 		      unsigned int stream,
-		      struct v4l2_mbus_framefmt *format)
+		      struct v4l2_mbus_framefmt *format,
+		      enum v4l2_subdev_format_whence which)
 {
 	int ret;
 
@@ -975,7 +985,7 @@  static int set_format(struct media_pad *pad,
 		  pad->entity->info.name, pad->index, stream);
 
 	ret = v4l2_subdev_set_format(pad->entity, format, pad->index, stream,
-				     V4L2_SUBDEV_FORMAT_ACTIVE);
+				     which);
 	if (ret < 0) {
 		media_dbg(pad->entity->media,
 			  "Unable to set format: %s (%d)\n",
@@ -992,7 +1002,8 @@  static int set_format(struct media_pad *pad,
 }
 
 static int set_selection(struct media_pad *pad, unsigned int stream,
-			 unsigned int target, struct v4l2_rect *rect)
+			 unsigned int target, struct v4l2_rect *rect,
+			 enum v4l2_subdev_format_whence which)
 {
 	int ret;
 
@@ -1005,7 +1016,7 @@  static int set_selection(struct media_pad *pad, unsigned int stream,
 		  pad->entity->info.name, pad->index, stream);
 
 	ret = v4l2_subdev_set_selection(pad->entity, rect, pad->index, stream,
-					target, V4L2_SUBDEV_FORMAT_ACTIVE);
+					target, which);
 	if (ret < 0) {
 		media_dbg(pad->entity->media,
 			  "Unable to set selection rectangle: %s (%d)\n",
@@ -1021,7 +1032,8 @@  static int set_selection(struct media_pad *pad, unsigned int stream,
 }
 
 static int set_frame_interval(struct media_pad *pad, unsigned int stream,
-			      struct v4l2_fract *interval)
+			      struct v4l2_fract *interval,
+			      enum v4l2_subdev_format_whence which)
 {
 	int ret;
 
@@ -1034,7 +1046,7 @@  static int set_frame_interval(struct media_pad *pad, unsigned int stream,
 		  pad->entity->info.name, pad->index, stream);
 
 	ret = v4l2_subdev_set_frame_interval(pad->entity, interval, pad->index,
-					     stream);
+					     stream, which);
 	if (ret < 0) {
 		media_dbg(pad->entity->media,
 			  "Unable to set frame interval: %s (%d)",
@@ -1050,6 +1062,7 @@  static int set_frame_interval(struct media_pad *pad, unsigned int stream,
 
 
 static int v4l2_subdev_parse_setup_format(struct media_device *media,
+					  enum v4l2_subdev_format_whence which,
 					  const char *p, char **endp)
 {
 	struct v4l2_mbus_framefmt format = { 0, 0, 0 };
@@ -1072,26 +1085,26 @@  static int v4l2_subdev_parse_setup_format(struct media_device *media,
 	}
 
 	if (pad->flags & MEDIA_PAD_FL_SINK) {
-		ret = set_format(pad, stream, &format);
+		ret = set_format(pad, stream, &format, which);
 		if (ret < 0)
 			return ret;
 	}
 
-	ret = set_selection(pad, stream, V4L2_SEL_TGT_CROP, &crop);
+	ret = set_selection(pad, stream, V4L2_SEL_TGT_CROP, &crop, which);
 	if (ret < 0)
 		return ret;
 
-	ret = set_selection(pad, stream, V4L2_SEL_TGT_COMPOSE, &compose);
+	ret = set_selection(pad, stream, V4L2_SEL_TGT_COMPOSE, &compose, which);
 	if (ret < 0)
 		return ret;
 
 	if (pad->flags & MEDIA_PAD_FL_SOURCE) {
-		ret = set_format(pad, stream, &format);
+		ret = set_format(pad, stream, &format, which);
 		if (ret < 0)
 			return ret;
 	}
 
-	ret = set_frame_interval(pad, stream, &interval);
+	ret = set_frame_interval(pad, stream, &interval, which);
 	if (ret < 0)
 		return ret;
 
@@ -1109,9 +1122,11 @@  static int v4l2_subdev_parse_setup_format(struct media_device *media,
 			if (link->source == pad &&
 			    link->sink->entity->info.type == MEDIA_ENT_T_V4L2_SUBDEV) {
 				remote_format = format;
-				set_format(link->sink, stream, &remote_format);
+				set_format(link->sink, stream, &remote_format,
+					   which);
 
-				ret = set_frame_interval(link->sink, stream, &interval);
+				ret = set_frame_interval(link->sink, stream,
+							 &interval, which);
 				if (ret < 0 && ret != -EINVAL && ret != -ENOTTY)
 					return ret;
 			}
@@ -1122,13 +1137,15 @@  static int v4l2_subdev_parse_setup_format(struct media_device *media,
 	return 0;
 }
 
-int v4l2_subdev_parse_setup_formats(struct media_device *media, const char *p)
+int v4l2_subdev_parse_setup_formats(struct media_device *media,
+				    enum v4l2_subdev_format_whence which,
+				    const char *p)
 {
 	char *end;
 	int ret;
 
 	do {
-		ret = v4l2_subdev_parse_setup_format(media, p, &end);
+		ret = v4l2_subdev_parse_setup_format(media, which, p, &end);
 		if (ret < 0)
 			return ret;
 
diff --git a/utils/media-ctl/media-ctl.c b/utils/media-ctl/media-ctl.c
index 1a9e393ac1f3..44256df953db 100644
--- a/utils/media-ctl/media-ctl.c
+++ b/utils/media-ctl/media-ctl.c
@@ -108,7 +108,8 @@  static void v4l2_subdev_print_format(struct media_entity *entity,
 	if (ret != 0)
 		return;
 
-	ret = v4l2_subdev_get_frame_interval(entity, &interval, pad, stream);
+	ret = v4l2_subdev_get_frame_interval(entity, &interval, pad, stream,
+					     V4L2_SUBDEV_FORMAT_ACTIVE);
 	if (ret != 0 && ret != -ENOTTY && ret != -EINVAL)
 		return;
 
@@ -527,7 +528,8 @@  static void media_print_topology_text_entity(struct media_device *media,
 	unsigned int padding;
 
 	if (media_entity_type(entity) == MEDIA_ENT_T_V4L2_SUBDEV)
-		v4l2_subdev_get_routing(entity, &routes, &num_routes);
+		v4l2_subdev_get_routing(entity, &routes, &num_routes,
+					V4L2_SUBDEV_FORMAT_ACTIVE);
 
 	padding = printf("- entity %u: ", info->id);
 	printf("%s (%u pad%s, %u link%s", info->name,
@@ -738,7 +740,9 @@  int main(int argc, char **argv)
 	}
 
 	if (media_opts.routes) {
-		ret = v4l2_subdev_parse_setup_routes(media, media_opts.routes);
+		ret = v4l2_subdev_parse_setup_routes(media,
+						     V4L2_SUBDEV_FORMAT_ACTIVE,
+						     media_opts.routes);
 		if (ret) {
 			printf("Unable to setup routes: %s (%d)\n",
 			       strerror(-ret), -ret);
@@ -748,6 +752,7 @@  int main(int argc, char **argv)
 
 	if (media_opts.formats) {
 		ret = v4l2_subdev_parse_setup_formats(media,
+						      V4L2_SUBDEV_FORMAT_ACTIVE,
 						      media_opts.formats);
 		if (ret) {
 			printf("Unable to setup formats: %s (%d)\n",
diff --git a/utils/media-ctl/v4l2subdev.h b/utils/media-ctl/v4l2subdev.h
index 1277040bfeae..0c1feae28e88 100644
--- a/utils/media-ctl/v4l2subdev.h
+++ b/utils/media-ctl/v4l2subdev.h
@@ -142,32 +142,44 @@  int v4l2_subdev_set_selection(struct media_entity *entity,
  * @param entity - subdev-device media entity.
  * @param routes - routes of the subdev.
  * @param num_routes - number of routes.
+ * @param which - identifier of the routes to get.
  *
  * Get the routes of @a entity and return them in an allocated array in @a routes
  * and the number of routes in @a num_routes.
  *
  * The caller is responsible for freeing the routes array after use.
  *
+ * @a which is set to V4L2_SUBDEV_FORMAT_TRY to get the routing table stored in
+ * the file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to get the device's active
+ * routing table.
+ *
  * @return 0 on success, or a negative error code on failure.
  */
 int v4l2_subdev_get_routing(struct media_entity *entity,
 			    struct v4l2_subdev_route **routes,
-			    unsigned int *num_routes);
+			    unsigned int *num_routes,
+			    enum v4l2_subdev_format_whence which);
 
 /**
  * @brief Set the routing table of a subdev media entity.
  * @param entity - subdev-device media entity.
  * @param routes - routes of the subdev.
  * @param num_routes - number of routes.
+ * @param which - identifier of the routes to set.
  *
  * Set the routes of @a entity. The routes are given in @a routes with the
  * length of @a num_routes.
  *
+ * @a which is set to V4L2_SUBDEV_FORMAT_TRY to set the routing table stored in
+ * the file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to set the device's active
+ * routing table.
+ *
  * @return 0 on success, or a negative error code on failure.
  */
 int v4l2_subdev_set_routing(struct media_entity *entity,
 			    struct v4l2_subdev_route *route,
-			    unsigned int num_routes);
+			    unsigned int num_routes,
+			    enum v4l2_subdev_format_whence which);
 
 /**
  * @brief Query the digital video capabilities of a pad.
@@ -228,6 +240,7 @@  int v4l2_subdev_set_dv_timings(struct media_entity *entity,
  * @param interval - frame interval to be filled.
  * @param pad - pad number.
  * @param stream - stream number.
+ * @param which - identifier of the interval to get.
  *
  * Retrieve the current frame interval on subdev @a entity and store it in the
  * @a interval structure.
@@ -235,11 +248,16 @@  int v4l2_subdev_set_dv_timings(struct media_entity *entity,
  * Frame interval retrieving is usually supported only on devices at the
  * beginning of video pipelines, such as sensors.
  *
+ * @a which is set to V4L2_SUBDEV_FORMAT_TRY to get the frame interval stored
+ * in the file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to get the device's active
+ * frame interval.
+ *
  * @return 0 on success, or a negative error code on failure.
  */
 
 int v4l2_subdev_get_frame_interval(struct media_entity *entity,
-	struct v4l2_fract *interval, unsigned int pad, unsigned int stream);
+	struct v4l2_fract *interval, unsigned int pad, unsigned int stream,
+	enum v4l2_subdev_format_whence which);
 
 /**
  * @brief Set the frame interval on a sub-device.
@@ -247,6 +265,7 @@  int v4l2_subdev_get_frame_interval(struct media_entity *entity,
  * @param interval - frame interval.
  * @param pad - pad number.
  * @param stream - stream number.
+ * @param which - identifier of the interval to set.
  *
  * Set the frame interval on subdev @a entity to @a interval. The driver is
  * allowed to modify the requested frame interval, in which case @a interval is
@@ -255,14 +274,20 @@  int v4l2_subdev_get_frame_interval(struct media_entity *entity,
  * Frame interval setting is usually supported only on devices at the beginning
  * of video pipelines, such as sensors.
  *
+ * @a which is set to V4L2_SUBDEV_FORMAT_TRY to set the frame interval stored
+ * in the file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to set the device's active
+ * frame interval.
+ *
  * @return 0 on success, or a negative error code on failure.
  */
 int v4l2_subdev_set_frame_interval(struct media_entity *entity,
-	struct v4l2_fract *interval, unsigned int pad, unsigned int stream);
+	struct v4l2_fract *interval, unsigned int pad, unsigned int stream,
+	enum v4l2_subdev_format_whence which);
 
 /**
  * @brief Parse a string and apply format, crop and frame interval settings.
  * @param media - media device.
+ * @param which - identifier of the parameters to set.
  * @param p - input string
  * @param endp - pointer to string p where parsing ended (return)
  *
@@ -272,20 +297,32 @@  int v4l2_subdev_set_frame_interval(struct media_entity *entity,
  *
  * Format strings are separeted by commas (,).
  *
+ * @a which is set to V4L2_SUBDEV_FORMAT_TRY to set the parameters stored in the
+ * file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to set the device's active
+ * parameters.
+ *
  * @return 0 on success, or a negative error code on failure.
  */
-int v4l2_subdev_parse_setup_formats(struct media_device *media, const char *p);
+int v4l2_subdev_parse_setup_formats(struct media_device *media,
+				    enum v4l2_subdev_format_whence which,
+				    const char *p);
 
 /**
  * @brief Parse a string and apply route settings.
  * @param media - media device.
+ * @param which - identifier of the routes to set.
  * @param p - input string
  *
  * Parse string @a p and apply route settings to a subdev.
  *
+ * @a which is set to V4L2_SUBDEV_FORMAT_TRY to set the routes stored in the
+ * file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to set the device's active routes.
+ *
  * @return 0 on success, or a negative error code on failure.
  */
-int v4l2_subdev_parse_setup_routes(struct media_device *media, const char *p);
+int v4l2_subdev_parse_setup_routes(struct media_device *media,
+				   enum v4l2_subdev_format_whence which,
+				   const char *p);
 
 /**
  * @brief Convert media bus pixel code to string.