>From 82fbf487ba9ca0dfd2d624c73a78f3741c974d3e Mon Sep 17 00:00:00 2001 From: Steve Longerbeam Date: Mon, 20 Feb 2017 15:13:15 -0800 Subject: [PATCH 15/37] [media] v4l: subdev: Add function to validate frame interval If the pads on both sides of a link specify a frame interval, then those frame intervals should match. Create the exported function v4l2_subdev_link_validate_frame_interval() for this purpose. This function is also added to v4l2_subdev_link_validate_default(). Signed-off-by: Steve Longerbeam --- Documentation/media/kapi/v4l2-subdev.rst | 5 ++-- drivers/media/v4l2-core/v4l2-subdev.c | 50 +++++++++++++++++++++++++++++++- include/media/v4l2-subdev.h | 10 +++++++ 3 files changed, 62 insertions(+), 3 deletions(-) diff --git a/Documentation/media/kapi/v4l2-subdev.rst b/Documentation/media/kapi/v4l2-subdev.rst index e1f0b72..5e424f6 100644 --- a/Documentation/media/kapi/v4l2-subdev.rst +++ b/Documentation/media/kapi/v4l2-subdev.rst @@ -132,8 +132,9 @@ of the format configuration between sub-devices and video nodes. If link_validate op is not set, the default function :c:func:`v4l2_subdev_link_validate_default` is used instead. This function -ensures that width, height and the media bus pixel code are equal on both source -and sink of the link. Subdev drivers are also free to use this function to +ensures that width, height, the media bus pixel code, and the frame +interval (if indicated by both sides), are equal on both source and +sink of the link. Subdev drivers are also free to use this function to perform the checks mentioned above in addition to their own checks. There are currently two ways to register subdevices with the V4L2 core. The diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index da78497..23a3e74 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -497,6 +497,50 @@ const struct v4l2_file_operations v4l2_subdev_fops = { }; #ifdef CONFIG_MEDIA_CONTROLLER +static int +v4l2_subdev_link_validate_get_fi(struct media_pad *pad, + struct v4l2_subdev_frame_interval *fi) +{ + if (is_media_entity_v4l2_subdev(pad->entity)) { + struct v4l2_subdev *sd = + media_entity_to_v4l2_subdev(pad->entity); + + fi->pad = pad->index; + return v4l2_subdev_call(sd, video, g_frame_interval, fi); + } + + WARN(pad->entity->function != MEDIA_ENT_F_IO_V4L, + "Driver bug! Wrong media entity type 0x%08x, entity %s\n", + pad->entity->function, pad->entity->name); + + return -EINVAL; +} + +int v4l2_subdev_link_validate_frame_interval(struct media_link *link) +{ + struct v4l2_subdev_frame_interval src_fi, sink_fi; + unsigned long src_usec, sink_usec; + int rval; + + rval = v4l2_subdev_link_validate_get_fi(link->source, &src_fi); + if (rval < 0) + return 0; + + rval = v4l2_subdev_link_validate_get_fi(link->sink, &sink_fi); + if (rval < 0) + return 0; + + src_usec = DIV_ROUND_CLOSEST_ULL( + (u64)src_fi.interval.numerator * USEC_PER_SEC, + src_fi.interval.denominator); + sink_usec = DIV_ROUND_CLOSEST_ULL( + (u64)sink_fi.interval.numerator * USEC_PER_SEC, + sink_fi.interval.denominator); + + return (src_usec != sink_usec) ? -EPIPE : 0; +} +EXPORT_SYMBOL_GPL(v4l2_subdev_link_validate_frame_interval); + int v4l2_subdev_link_validate_default(struct v4l2_subdev *sd, struct media_link *link, struct v4l2_subdev_format *source_fmt, @@ -516,7 +560,11 @@ int v4l2_subdev_link_validate_default(struct v4l2_subdev *sd, sink_fmt->format.field != V4L2_FIELD_NONE) return -EPIPE; - return 0; + /* + * The frame interval must match if specified on both ends + * of the link. + */ + return v4l2_subdev_link_validate_frame_interval(link); } EXPORT_SYMBOL_GPL(v4l2_subdev_link_validate_default); diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 0ab1c5d..60c941d 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -929,6 +929,16 @@ int v4l2_subdev_link_validate_default(struct v4l2_subdev *sd, struct v4l2_subdev_format *sink_fmt); /** + * v4l2_subdev_link_validate_frame_interval - validates a media link + * + * @link: pointer to &struct media_link + * + * This function ensures that the frame intervals, if specified by + * both the source and sink subdevs of the link, are equal. + */ +int v4l2_subdev_link_validate_frame_interval(struct media_link *link); + +/** * v4l2_subdev_link_validate - validates a media link * * @link: pointer to &struct media_link -- 2.7.4