mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 01:53:29 +02:00
media: subdev: Add v4l2_subdev_get_frame_desc_passthrough helper
Add a helper for v4l2_subdev_pad_ops.v4l2_get_frame_desc operation. The helper can be used when the subdevice directly passes through the streams. Signed-off-by: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
This commit is contained in:
parent
291d75952c
commit
a564839e63
|
|
@ -2545,6 +2545,119 @@ int v4l2_subdev_s_stream_helper(struct v4l2_subdev *sd, int enable)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(v4l2_subdev_s_stream_helper);
|
EXPORT_SYMBOL_GPL(v4l2_subdev_s_stream_helper);
|
||||||
|
|
||||||
|
int v4l2_subdev_get_frame_desc_passthrough(struct v4l2_subdev *sd,
|
||||||
|
unsigned int pad,
|
||||||
|
struct v4l2_mbus_frame_desc *fd)
|
||||||
|
{
|
||||||
|
const struct media_pad *pads = sd->entity.pads;
|
||||||
|
struct media_pad *local_sink_pad;
|
||||||
|
struct v4l2_subdev_route *route;
|
||||||
|
struct v4l2_subdev_state *state;
|
||||||
|
struct device *dev = sd->dev;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (WARN_ON(!(pads[pad].flags & MEDIA_PAD_FL_SOURCE)))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
state = v4l2_subdev_lock_and_get_active_state(sd);
|
||||||
|
|
||||||
|
/* Iterate over sink pads */
|
||||||
|
media_entity_for_each_pad(&sd->entity, local_sink_pad) {
|
||||||
|
struct v4l2_mbus_frame_desc source_fd;
|
||||||
|
bool have_source_fd = false;
|
||||||
|
|
||||||
|
if (!(local_sink_pad->flags & MEDIA_PAD_FL_SINK))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy frame desc entries for the streams going from the sink
|
||||||
|
* pad to the requested pad
|
||||||
|
*/
|
||||||
|
for_each_active_route(&state->routing, route) {
|
||||||
|
struct v4l2_mbus_frame_desc_entry *source_entry = NULL;
|
||||||
|
struct media_pad *remote_source_pad;
|
||||||
|
struct v4l2_subdev *remote_sd;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if (route->source_pad != pad ||
|
||||||
|
route->sink_pad != local_sink_pad->index)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!have_source_fd) {
|
||||||
|
remote_source_pad = media_pad_remote_pad_unique(local_sink_pad);
|
||||||
|
if (!remote_source_pad) {
|
||||||
|
dev_dbg(dev, "Failed to find remote pad for sink pad %u\n",
|
||||||
|
local_sink_pad->index);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out_unlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
remote_sd = media_entity_to_v4l2_subdev(remote_source_pad->entity);
|
||||||
|
if (!remote_sd) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out_unlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = v4l2_subdev_call(remote_sd, pad,
|
||||||
|
get_frame_desc,
|
||||||
|
remote_source_pad->index,
|
||||||
|
&source_fd);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev,
|
||||||
|
"Failed to get frame desc from remote subdev %s\n",
|
||||||
|
remote_sd->name);
|
||||||
|
goto out_unlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
have_source_fd = true;
|
||||||
|
|
||||||
|
if (fd->num_entries == 0) {
|
||||||
|
fd->type = source_fd.type;
|
||||||
|
} else if (fd->type != source_fd.type) {
|
||||||
|
dev_err(dev,
|
||||||
|
"Frame desc type mismatch: %u != %u\n",
|
||||||
|
fd->type, source_fd.type);
|
||||||
|
ret = -EPIPE;
|
||||||
|
goto out_unlock;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < source_fd.num_entries; i++) {
|
||||||
|
if (source_fd.entry[i].stream == route->sink_stream) {
|
||||||
|
source_entry = &source_fd.entry[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!source_entry) {
|
||||||
|
dev_dbg(sd->dev,
|
||||||
|
"Failed to find stream %u from source frame desc\n",
|
||||||
|
route->sink_stream);
|
||||||
|
ret = -EPIPE;
|
||||||
|
goto out_unlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fd->num_entries >= V4L2_FRAME_DESC_ENTRY_MAX) {
|
||||||
|
dev_dbg(sd->dev, "Frame desc entry limit reached\n");
|
||||||
|
ret = -ENOSPC;
|
||||||
|
goto out_unlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd->entry[fd->num_entries] = *source_entry;
|
||||||
|
|
||||||
|
fd->entry[fd->num_entries].stream = route->source_stream;
|
||||||
|
|
||||||
|
fd->num_entries++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out_unlock:
|
||||||
|
v4l2_subdev_unlock_state(state);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(v4l2_subdev_get_frame_desc_passthrough);
|
||||||
|
|
||||||
#endif /* CONFIG_VIDEO_V4L2_SUBDEV_API */
|
#endif /* CONFIG_VIDEO_V4L2_SUBDEV_API */
|
||||||
|
|
||||||
#endif /* CONFIG_MEDIA_CONTROLLER */
|
#endif /* CONFIG_MEDIA_CONTROLLER */
|
||||||
|
|
|
||||||
|
|
@ -1722,6 +1722,28 @@ int v4l2_subdev_disable_streams(struct v4l2_subdev *sd, u32 pad,
|
||||||
*/
|
*/
|
||||||
int v4l2_subdev_s_stream_helper(struct v4l2_subdev *sd, int enable);
|
int v4l2_subdev_s_stream_helper(struct v4l2_subdev *sd, int enable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* v4l2_subdev_get_frame_desc_passthrough() - Helper to implement the subdev
|
||||||
|
* v4l2_get_frame_desc operation in simple passthrough cases
|
||||||
|
* @sd: The subdevice
|
||||||
|
* @pad: The source pad index
|
||||||
|
* @fd: The mbus frame desc
|
||||||
|
*
|
||||||
|
* Subdevice drivers that only pass through the streams can use this helper
|
||||||
|
* to implement the &v4l2_subdev_pad_ops.v4l2_get_frame_desc operation.
|
||||||
|
*
|
||||||
|
* The helper will call get_frame_desc on the subdevice's sources, create a new
|
||||||
|
* frame desc which contains only the streams on the given source pad. The data
|
||||||
|
* for each frame desc entry is copied directly from the data provided from the
|
||||||
|
* calls to the subdevice's sources, with the exception of the 'stream' field
|
||||||
|
* which is set according to the subdevice's routing table.
|
||||||
|
*
|
||||||
|
* Return: 0 on success, or a negative error code otherwise.
|
||||||
|
*/
|
||||||
|
int v4l2_subdev_get_frame_desc_passthrough(struct v4l2_subdev *sd,
|
||||||
|
unsigned int pad,
|
||||||
|
struct v4l2_mbus_frame_desc *fd);
|
||||||
|
|
||||||
#endif /* CONFIG_VIDEO_V4L2_SUBDEV_API */
|
#endif /* CONFIG_VIDEO_V4L2_SUBDEV_API */
|
||||||
|
|
||||||
#endif /* CONFIG_MEDIA_CONTROLLER */
|
#endif /* CONFIG_MEDIA_CONTROLLER */
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user