Commit 3cc7a4bb authored by Tomi Valkeinen's avatar Tomi Valkeinen Committed by Mauro Carvalho Chehab

media: subdev: pass also the active state to subdevs from ioctls

At the moment when a subdev op is called, the TRY subdev state
(subdev_fh->state) is passed as a parameter even for the ACTIVE case, or
alternatively a NULL can be passed for ACTIVE case. This used to make
sense, as the ACTIVE state was handled internally by the subdev drivers.

We now have a state for the ACTIVE case in a standard place, and can
pass that also to the drivers. This patch changes the subdev ioctls to
either pass the TRY or ACTIVE state to the subdev.

Unfortunately many drivers call ops from other subdevs, and implicitly
pass NULL as the state, so this is just a partial solution. A coccinelle
spatch could perhaps be created which fixes the drivers' subdev calls.

For all current upstream drivers this doesn't matter, as they do not
expect to get a valid state for ACTIVE case. But future drivers which
support multiplexed streaming and routing will depend on getting a state
for both active and try cases.

For new drivers we can mandate that the pipelines where the drivers are
used need to pass the state properly, or preferably, not call such
subdev ops at all.

However, if an existing subdev driver is changed to support multiplexed
streams, the driver has to consider cases where its ops will be called
with NULL state. The problem can easily be solved by using the
v4l2_subdev_lock_and_get_active_state() helper, introduced in a follow
up patch.

Another follow up patch adds wrappers for pad ops dealing with subdev
state, which automate the use of
v4l2_subdev_lock_and_get_active_state() for cases where the state is
NULL.
Signed-off-by: default avatarTomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Reviewed-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Reviewed-by: default avatarJacopo Mondi <jacopo+renesas@jmondi.org>
Reviewed-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: default avatarSakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@kernel.org>
parent 2f91838c
......@@ -344,6 +344,44 @@ const struct v4l2_subdev_ops v4l2_subdev_call_wrappers = {
EXPORT_SYMBOL(v4l2_subdev_call_wrappers);
#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
static struct v4l2_subdev_state *
subdev_ioctl_get_state(struct v4l2_subdev *sd, struct v4l2_subdev_fh *subdev_fh,
unsigned int cmd, void *arg)
{
u32 which;
switch (cmd) {
default:
return NULL;
case VIDIOC_SUBDEV_G_FMT:
case VIDIOC_SUBDEV_S_FMT:
which = ((struct v4l2_subdev_format *)arg)->which;
break;
case VIDIOC_SUBDEV_G_CROP:
case VIDIOC_SUBDEV_S_CROP:
which = ((struct v4l2_subdev_crop *)arg)->which;
break;
case VIDIOC_SUBDEV_ENUM_MBUS_CODE:
which = ((struct v4l2_subdev_mbus_code_enum *)arg)->which;
break;
case VIDIOC_SUBDEV_ENUM_FRAME_SIZE:
which = ((struct v4l2_subdev_frame_size_enum *)arg)->which;
break;
case VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL:
which = ((struct v4l2_subdev_frame_interval_enum *)arg)->which;
break;
case VIDIOC_SUBDEV_G_SELECTION:
case VIDIOC_SUBDEV_S_SELECTION:
which = ((struct v4l2_subdev_selection *)arg)->which;
break;
}
return which == V4L2_SUBDEV_FORMAT_TRY ?
subdev_fh->state :
v4l2_subdev_get_active_state(sd);
}
static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct video_device *vdev = video_devdata(file);
......@@ -351,8 +389,11 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
struct v4l2_fh *vfh = file->private_data;
struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh);
bool ro_subdev = test_bit(V4L2_FL_SUBDEV_RO_DEVNODE, &vdev->flags);
struct v4l2_subdev_state *state;
int rval;
state = subdev_ioctl_get_state(sd, subdev_fh, cmd, arg);
switch (cmd) {
case VIDIOC_SUBDEV_QUERYCAP: {
struct v4l2_subdev_capability *cap = arg;
......@@ -475,7 +516,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
memset(format->reserved, 0, sizeof(format->reserved));
memset(format->format.reserved, 0, sizeof(format->format.reserved));
return v4l2_subdev_call(sd, pad, get_fmt, subdev_fh->state, format);
return v4l2_subdev_call(sd, pad, get_fmt, state, format);
}
case VIDIOC_SUBDEV_S_FMT: {
......@@ -486,7 +527,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
memset(format->reserved, 0, sizeof(format->reserved));
memset(format->format.reserved, 0, sizeof(format->format.reserved));
return v4l2_subdev_call(sd, pad, set_fmt, subdev_fh->state, format);
return v4l2_subdev_call(sd, pad, set_fmt, state, format);
}
case VIDIOC_SUBDEV_G_CROP: {
......@@ -500,7 +541,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
sel.target = V4L2_SEL_TGT_CROP;
rval = v4l2_subdev_call(
sd, pad, get_selection, subdev_fh->state, &sel);
sd, pad, get_selection, state, &sel);
crop->rect = sel.r;
......@@ -522,7 +563,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
sel.r = crop->rect;
rval = v4l2_subdev_call(
sd, pad, set_selection, subdev_fh->state, &sel);
sd, pad, set_selection, state, &sel);
crop->rect = sel.r;
......@@ -533,7 +574,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
struct v4l2_subdev_mbus_code_enum *code = arg;
memset(code->reserved, 0, sizeof(code->reserved));
return v4l2_subdev_call(sd, pad, enum_mbus_code, subdev_fh->state,
return v4l2_subdev_call(sd, pad, enum_mbus_code, state,
code);
}
......@@ -541,7 +582,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
struct v4l2_subdev_frame_size_enum *fse = arg;
memset(fse->reserved, 0, sizeof(fse->reserved));
return v4l2_subdev_call(sd, pad, enum_frame_size, subdev_fh->state,
return v4l2_subdev_call(sd, pad, enum_frame_size, state,
fse);
}
......@@ -566,7 +607,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
struct v4l2_subdev_frame_interval_enum *fie = arg;
memset(fie->reserved, 0, sizeof(fie->reserved));
return v4l2_subdev_call(sd, pad, enum_frame_interval, subdev_fh->state,
return v4l2_subdev_call(sd, pad, enum_frame_interval, state,
fie);
}
......@@ -575,7 +616,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
memset(sel->reserved, 0, sizeof(sel->reserved));
return v4l2_subdev_call(
sd, pad, get_selection, subdev_fh->state, sel);
sd, pad, get_selection, state, sel);
}
case VIDIOC_SUBDEV_S_SELECTION: {
......@@ -586,7 +627,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
memset(sel->reserved, 0, sizeof(sel->reserved));
return v4l2_subdev_call(
sd, pad, set_selection, subdev_fh->state, sel);
sd, pad, set_selection, state, sel);
}
case VIDIOC_G_EDID: {
......@@ -820,10 +861,13 @@ v4l2_subdev_link_validate_get_format(struct media_pad *pad,
if (is_media_entity_v4l2_subdev(pad->entity)) {
struct v4l2_subdev *sd =
media_entity_to_v4l2_subdev(pad->entity);
struct v4l2_subdev_state *state;
state = v4l2_subdev_get_active_state(sd);
fmt->which = V4L2_SUBDEV_FORMAT_ACTIVE;
fmt->pad = pad->index;
return v4l2_subdev_call(sd, pad, get_fmt, NULL, fmt);
return v4l2_subdev_call(sd, pad, get_fmt, state, fmt);
}
WARN(pad->entity->function != MEDIA_ENT_F_IO_V4L,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment