mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-04 20:19:47 +08:00
[media] v4l: Implement v4l2_subdev_link_validate()
v4l2_subdev_link_validate() is the default op for validating a link. In V4L2 subdev context, it is used to call a pad op which performs the proper link check without much extra work. Signed-off-by: Sakari Ailus <sakari.ailus@iki.fi> Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
48398f932b
commit
8227c92b69
@ -316,6 +316,18 @@ If the subdev driver intends to process video and integrate with the media
|
|||||||
framework, it must implement format related functionality using
|
framework, it must implement format related functionality using
|
||||||
v4l2_subdev_pad_ops instead of v4l2_subdev_video_ops.
|
v4l2_subdev_pad_ops instead of v4l2_subdev_video_ops.
|
||||||
|
|
||||||
|
In that case, the subdev driver may set the link_validate field to provide
|
||||||
|
its own link validation function. The link validation function is called for
|
||||||
|
every link in the pipeline where both of the ends of the links are V4L2
|
||||||
|
sub-devices. The driver is still responsible for validating the correctness
|
||||||
|
of the format configuration between sub-devices and video nodes.
|
||||||
|
|
||||||
|
If link_validate op is not set, the default function
|
||||||
|
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
|
||||||
|
perform the checks mentioned above in addition to their own checks.
|
||||||
|
|
||||||
A device (bridge) driver needs to register the v4l2_subdev with the
|
A device (bridge) driver needs to register the v4l2_subdev with the
|
||||||
v4l2_device:
|
v4l2_device:
|
||||||
|
|
||||||
|
@ -387,6 +387,70 @@ const struct v4l2_file_operations v4l2_subdev_fops = {
|
|||||||
.poll = subdev_poll,
|
.poll = subdev_poll,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_MEDIA_CONTROLLER
|
||||||
|
int v4l2_subdev_link_validate_default(struct v4l2_subdev *sd,
|
||||||
|
struct media_link *link,
|
||||||
|
struct v4l2_subdev_format *source_fmt,
|
||||||
|
struct v4l2_subdev_format *sink_fmt)
|
||||||
|
{
|
||||||
|
if (source_fmt->format.width != sink_fmt->format.width
|
||||||
|
|| source_fmt->format.height != sink_fmt->format.height
|
||||||
|
|| source_fmt->format.code != sink_fmt->format.code)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(v4l2_subdev_link_validate_default);
|
||||||
|
|
||||||
|
static int
|
||||||
|
v4l2_subdev_link_validate_get_format(struct media_pad *pad,
|
||||||
|
struct v4l2_subdev_format *fmt)
|
||||||
|
{
|
||||||
|
switch (media_entity_type(pad->entity)) {
|
||||||
|
case MEDIA_ENT_T_V4L2_SUBDEV:
|
||||||
|
fmt->which = V4L2_SUBDEV_FORMAT_ACTIVE;
|
||||||
|
fmt->pad = pad->index;
|
||||||
|
return v4l2_subdev_call(media_entity_to_v4l2_subdev(
|
||||||
|
pad->entity),
|
||||||
|
pad, get_fmt, NULL, fmt);
|
||||||
|
default:
|
||||||
|
WARN(1, "Driver bug! Wrong media entity type %d, entity %s\n",
|
||||||
|
media_entity_type(pad->entity), pad->entity->name);
|
||||||
|
/* Fall through */
|
||||||
|
case MEDIA_ENT_T_DEVNODE_V4L:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int v4l2_subdev_link_validate(struct media_link *link)
|
||||||
|
{
|
||||||
|
struct v4l2_subdev *sink;
|
||||||
|
struct v4l2_subdev_format sink_fmt, source_fmt;
|
||||||
|
int rval;
|
||||||
|
|
||||||
|
rval = v4l2_subdev_link_validate_get_format(
|
||||||
|
link->source, &source_fmt);
|
||||||
|
if (rval < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
rval = v4l2_subdev_link_validate_get_format(
|
||||||
|
link->sink, &sink_fmt);
|
||||||
|
if (rval < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
sink = media_entity_to_v4l2_subdev(link->sink->entity);
|
||||||
|
|
||||||
|
rval = v4l2_subdev_call(sink, pad, link_validate, link,
|
||||||
|
&source_fmt, &sink_fmt);
|
||||||
|
if (rval != -ENOIOCTLCMD)
|
||||||
|
return rval;
|
||||||
|
|
||||||
|
return v4l2_subdev_link_validate_default(
|
||||||
|
sink, link, &source_fmt, &sink_fmt);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(v4l2_subdev_link_validate);
|
||||||
|
#endif /* CONFIG_MEDIA_CONTROLLER */
|
||||||
|
|
||||||
void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops)
|
void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops)
|
||||||
{
|
{
|
||||||
INIT_LIST_HEAD(&sd->list);
|
INIT_LIST_HEAD(&sd->list);
|
||||||
|
@ -470,6 +470,11 @@ struct v4l2_subdev_pad_ops {
|
|||||||
struct v4l2_subdev_selection *sel);
|
struct v4l2_subdev_selection *sel);
|
||||||
int (*set_selection)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
|
int (*set_selection)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
|
||||||
struct v4l2_subdev_selection *sel);
|
struct v4l2_subdev_selection *sel);
|
||||||
|
#ifdef CONFIG_MEDIA_CONTROLLER
|
||||||
|
int (*link_validate)(struct v4l2_subdev *sd, struct media_link *link,
|
||||||
|
struct v4l2_subdev_format *source_fmt,
|
||||||
|
struct v4l2_subdev_format *sink_fmt);
|
||||||
|
#endif /* CONFIG_MEDIA_CONTROLLER */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct v4l2_subdev_ops {
|
struct v4l2_subdev_ops {
|
||||||
@ -602,6 +607,13 @@ static inline void *v4l2_get_subdev_hostdata(const struct v4l2_subdev *sd)
|
|||||||
return sd->host_priv;
|
return sd->host_priv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_MEDIA_CONTROLLER
|
||||||
|
int v4l2_subdev_link_validate_default(struct v4l2_subdev *sd,
|
||||||
|
struct media_link *link,
|
||||||
|
struct v4l2_subdev_format *source_fmt,
|
||||||
|
struct v4l2_subdev_format *sink_fmt);
|
||||||
|
int v4l2_subdev_link_validate(struct media_link *link);
|
||||||
|
#endif /* CONFIG_MEDIA_CONTROLLER */
|
||||||
void v4l2_subdev_init(struct v4l2_subdev *sd,
|
void v4l2_subdev_init(struct v4l2_subdev *sd,
|
||||||
const struct v4l2_subdev_ops *ops);
|
const struct v4l2_subdev_ops *ops);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user